ValidationError-ify commands, add some validation to UnsafeCommandBufferBuilder (#2266)

* ValidationError-ify commands, add some validation to `UnsafeCommandBufferBuilder`

* Use `SubpassBeginInfo` for the triangle example
This commit is contained in:
Rua 2023-08-04 20:55:16 +02:00 committed by GitHub
parent 0cb0728776
commit d0144c2d98
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
69 changed files with 17022 additions and 11347 deletions

View File

@ -52,7 +52,7 @@ use vulkano::{
command_buffer::{
allocator::StandardCommandBufferAllocator, AutoCommandBufferBuilder, BufferImageCopy,
ClearColorImageInfo, CommandBufferUsage, CopyBufferToImageInfo,
PrimaryCommandBufferAbstract, RenderPassBeginInfo, SubpassContents,
PrimaryCommandBufferAbstract, RenderPassBeginInfo,
},
descriptor_set::{
allocator::StandardDescriptorSetAllocator, PersistentDescriptorSet, WriteDescriptorSet,
@ -597,11 +597,13 @@ fn main() {
framebuffers[image_index as usize].clone(),
)
},
SubpassContents::Inline,
Default::default(),
)
.unwrap()
.set_viewport(0, [viewport.clone()].into_iter().collect())
.unwrap()
.bind_pipeline_graphics(pipeline.clone())
.unwrap()
.bind_descriptor_sets(
PipelineBindPoint::Graphics,
pipeline.layout().clone(),
@ -614,10 +616,12 @@ fn main() {
.clone(),
),
)
.unwrap()
.bind_vertex_buffers(0, vertex_buffer.clone())
.unwrap()
.draw(vertex_buffer.len() as u32, 1, 0, 0)
.unwrap()
.end_render_pass()
.end_render_pass(Default::default())
.unwrap();
let command_buffer = builder.build().unwrap();

View File

@ -213,12 +213,14 @@ fn main() {
// 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(
PipelineBindPoint::Compute,
pipeline.layout().clone(),
0,
set,
)
.unwrap()
.dispatch([1024, 1, 1])
.unwrap();

View File

@ -20,7 +20,7 @@ use vulkano::{
},
command_buffer::{
allocator::StandardCommandBufferAllocator, AutoCommandBufferBuilder, CommandBufferUsage,
RenderPassBeginInfo, SubpassContents,
RenderPassBeginInfo,
},
device::{
physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo,
@ -381,16 +381,19 @@ fn main() {
framebuffers[image_index as usize].clone(),
)
},
SubpassContents::Inline,
Default::default(),
)
.unwrap()
.set_viewport(0, [viewport.clone()].into_iter().collect())
.unwrap()
// Draw our buffer
.bind_pipeline_graphics(pipeline.clone())
.unwrap()
.bind_vertex_buffers(0, buffer)
.unwrap()
.draw(num_vertices, 1, 0, 0)
.unwrap()
.end_render_pass()
.end_render_pass(Default::default())
.unwrap();
let command_buffer = builder.build().unwrap();

View File

@ -11,7 +11,7 @@ use std::sync::Arc;
use vulkano::{
command_buffer::{
allocator::StandardCommandBufferAllocator, AutoCommandBufferBuilder, ClearAttachment,
ClearRect, CommandBufferUsage, RenderPassBeginInfo, SubpassContents,
ClearRect, CommandBufferUsage, RenderPassBeginInfo,
},
device::{
physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo,
@ -223,7 +223,7 @@ fn main() {
framebuffers[image_index as usize].clone(),
)
},
SubpassContents::Inline,
Default::default(),
)
.unwrap()
// Clear attachments with clear values and rects information. All the rects will be
@ -260,7 +260,7 @@ fn main() {
.collect(),
)
.unwrap()
.end_render_pass()
.end_render_pass(Default::default())
.unwrap();
let command_buffer = builder.build().unwrap();

View File

@ -198,15 +198,20 @@ impl AmbientLightingSystem {
.unwrap();
builder
.set_viewport(0, [viewport].into_iter().collect())
.unwrap()
.bind_pipeline_graphics(self.pipeline.clone())
.unwrap()
.bind_descriptor_sets(
PipelineBindPoint::Graphics,
self.pipeline.layout().clone(),
0,
descriptor_set,
)
.unwrap()
.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();
builder.build().unwrap()

View File

@ -212,15 +212,20 @@ impl DirectionalLightingSystem {
.unwrap();
builder
.set_viewport(0, [viewport].into_iter().collect())
.unwrap()
.bind_pipeline_graphics(self.pipeline.clone())
.unwrap()
.bind_descriptor_sets(
PipelineBindPoint::Graphics,
self.pipeline.layout().clone(),
0,
descriptor_set,
)
.unwrap()
.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();
builder.build().unwrap()

View File

@ -225,15 +225,20 @@ impl PointLightingSystem {
.unwrap();
builder
.set_viewport(0, [viewport].into_iter().collect())
.unwrap()
.bind_pipeline_graphics(self.pipeline.clone())
.unwrap()
.bind_descriptor_sets(
PipelineBindPoint::Graphics,
self.pipeline.layout().clone(),
0,
descriptor_set,
)
.unwrap()
.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();
builder.build().unwrap()

View File

@ -18,7 +18,7 @@ use vulkano::{
command_buffer::{
allocator::StandardCommandBufferAllocator, AutoCommandBufferBuilder, CommandBufferUsage,
PrimaryAutoCommandBuffer, RenderPassBeginInfo, SecondaryCommandBufferAbstract,
SubpassContents,
SubpassBeginInfo, SubpassContents,
},
descriptor_set::allocator::StandardDescriptorSetAllocator,
device::Queue,
@ -363,7 +363,10 @@ impl FrameSystem {
],
..RenderPassBeginInfo::framebuffer(framebuffer.clone())
},
SubpassContents::SecondaryCommandBuffers,
SubpassBeginInfo {
contents: SubpassContents::SecondaryCommandBuffers,
..Default::default()
},
)
.unwrap();
@ -428,7 +431,13 @@ impl<'a> Frame<'a> {
self.command_buffer_builder
.as_mut()
.unwrap()
.next_subpass(SubpassContents::SecondaryCommandBuffers)
.next_subpass(
Default::default(),
SubpassBeginInfo {
contents: SubpassContents::SecondaryCommandBuffers,
..Default::default()
},
)
.unwrap();
// And returning an object that will allow the user to apply lighting to the scene.
@ -442,7 +451,7 @@ impl<'a> Frame<'a> {
self.command_buffer_builder
.as_mut()
.unwrap()
.end_render_pass()
.end_render_pass(Default::default())
.unwrap();
let command_buffer = self.command_buffer_builder.take().unwrap().build().unwrap();

View File

@ -151,8 +151,11 @@ impl TriangleDrawSystem {
.into_iter()
.collect(),
)
.unwrap()
.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();
builder.build().unwrap()

View File

@ -250,12 +250,14 @@ fn main() {
#[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(
@ -264,6 +266,7 @@ fn main() {
0,
set.clone().offsets([1 * align as u32]),
)
.unwrap()
.dispatch([12, 1, 1])
.unwrap()
.bind_descriptor_sets(
@ -272,6 +275,7 @@ fn main() {
0,
set.offsets([2 * align as u32]),
)
.unwrap()
.dispatch([12, 1, 1])
.unwrap();
let command_buffer = builder.build().unwrap();

View File

@ -260,12 +260,14 @@ fn main() {
.unwrap();
builder
.bind_pipeline_compute(pipeline.clone())
.unwrap()
.bind_descriptor_sets(
PipelineBindPoint::Compute,
pipeline.layout().clone(),
0,
set,
)
.unwrap()
// Note that dispatch dimensions must be proportional to the local size.
.dispatch([1024 / local_size_x, 1024 / local_size_y, 1])
.unwrap()

View File

@ -18,7 +18,6 @@ mod linux {
command_buffer::{
allocator::StandardCommandBufferAllocator, AutoCommandBufferBuilder,
CommandBufferUsage, RenderPassBeginInfo, SemaphoreSubmitInfo, SubmitInfo,
SubpassContents,
},
descriptor_set::{
allocator::StandardDescriptorSetAllocator, PersistentDescriptorSet, WriteDescriptorSet,
@ -378,21 +377,25 @@ mod linux {
framebuffers[image_index as usize].clone(),
)
},
SubpassContents::Inline,
Default::default(),
)
.unwrap()
.set_viewport(0, [viewport.clone()].into_iter().collect())
.unwrap()
.bind_pipeline_graphics(pipeline.clone())
.unwrap()
.bind_descriptor_sets(
PipelineBindPoint::Graphics,
pipeline.layout().clone(),
0,
set.clone(),
)
.unwrap()
.bind_vertex_buffers(0, vertex_buffer.clone())
.unwrap()
.draw(vertex_buffer.len() as u32, 1, 0, 0)
.unwrap()
.end_render_pass()
.end_render_pass(Default::default())
.unwrap();
let command_buffer = builder.build().unwrap();

View File

@ -14,7 +14,6 @@ use vulkano::{
allocator::StandardCommandBufferAllocator, AutoCommandBufferBuilder, BlitImageInfo,
BufferImageCopy, ClearColorImageInfo, CommandBufferUsage, CopyBufferToImageInfo,
CopyImageInfo, ImageBlit, ImageCopy, PrimaryCommandBufferAbstract, RenderPassBeginInfo,
SubpassContents,
},
descriptor_set::{
allocator::StandardDescriptorSetAllocator, PersistentDescriptorSet, WriteDescriptorSet,
@ -471,21 +470,25 @@ fn main() {
framebuffers[image_index as usize].clone(),
)
},
SubpassContents::Inline,
Default::default(),
)
.unwrap()
.set_viewport(0, [viewport.clone()].into_iter().collect())
.unwrap()
.bind_pipeline_graphics(pipeline.clone())
.unwrap()
.bind_descriptor_sets(
PipelineBindPoint::Graphics,
pipeline.layout().clone(),
0,
set.clone(),
)
.unwrap()
.bind_vertex_buffers(0, vertex_buffer.clone())
.unwrap()
.draw(vertex_buffer.len() as u32, 1, 0, 0)
.unwrap()
.end_render_pass()
.end_render_pass(Default::default())
.unwrap();
let command_buffer = builder.build().unwrap();

View File

@ -12,7 +12,7 @@ use vulkano::{
buffer::{Buffer, BufferContents, BufferCreateInfo, BufferUsage},
command_buffer::{
allocator::StandardCommandBufferAllocator, AutoCommandBufferBuilder, CommandBufferUsage,
CopyBufferToImageInfo, PrimaryCommandBufferAbstract, RenderPassBeginInfo, SubpassContents,
CopyBufferToImageInfo, PrimaryCommandBufferAbstract, RenderPassBeginInfo,
},
descriptor_set::{
allocator::StandardDescriptorSetAllocator, PersistentDescriptorSet, WriteDescriptorSet,
@ -418,21 +418,25 @@ fn main() {
framebuffers[image_index as usize].clone(),
)
},
SubpassContents::Inline,
Default::default(),
)
.unwrap()
.set_viewport(0, [viewport.clone()].into_iter().collect())
.unwrap()
.bind_pipeline_graphics(pipeline.clone())
.unwrap()
.bind_descriptor_sets(
PipelineBindPoint::Graphics,
pipeline.layout().clone(),
0,
set.clone(),
)
.unwrap()
.bind_vertex_buffers(0, vertex_buffer.clone())
.unwrap()
.draw(vertex_buffer.len() as u32, 1, 0, 0)
.unwrap()
.end_render_pass()
.end_render_pass(Default::default())
.unwrap();
let command_buffer = builder.build().unwrap();

View File

@ -21,7 +21,7 @@ use vulkano::{
buffer::{Buffer, BufferContents, BufferCreateInfo, BufferUsage},
command_buffer::{
allocator::StandardCommandBufferAllocator, AutoCommandBufferBuilder, CommandBufferUsage,
CopyBufferToImageInfo, PrimaryCommandBufferAbstract, RenderPassBeginInfo, SubpassContents,
CopyBufferToImageInfo, PrimaryCommandBufferAbstract, RenderPassBeginInfo,
},
descriptor_set::{
allocator::StandardDescriptorSetAllocator, PersistentDescriptorSet, WriteDescriptorSet,
@ -439,21 +439,25 @@ fn main() {
framebuffers[image_index as usize].clone(),
)
},
SubpassContents::Inline,
Default::default(),
)
.unwrap()
.set_viewport(0, [viewport.clone()].into_iter().collect())
.unwrap()
.bind_pipeline_graphics(pipeline.clone())
.unwrap()
.bind_descriptor_sets(
PipelineBindPoint::Graphics,
pipeline.layout().clone(),
0,
set.clone(),
)
.unwrap()
.bind_vertex_buffers(0, vertex_buffer.clone())
.unwrap()
.draw(vertex_buffer.len() as u32, 1, 0, 0)
.unwrap()
.end_render_pass()
.end_render_pass(Default::default())
.unwrap();
let command_buffer = builder.build().unwrap();

View File

@ -31,7 +31,7 @@ use vulkano::{
},
command_buffer::{
allocator::StandardCommandBufferAllocator, AutoCommandBufferBuilder, CommandBufferUsage,
DrawIndirectCommand, RenderPassBeginInfo, SubpassContents,
DrawIndirectCommand, RenderPassBeginInfo,
},
descriptor_set::{
allocator::StandardDescriptorSetAllocator, PersistentDescriptorSet, WriteDescriptorSet,
@ -474,12 +474,14 @@ fn main() {
// vertices and fill out the draw call arguments.
builder
.bind_pipeline_compute(compute_pipeline.clone())
.unwrap()
.bind_descriptor_sets(
PipelineBindPoint::Compute,
compute_pipeline.layout().clone(),
0,
cs_desciptor_set,
)
.unwrap()
.dispatch([1, 1, 1])
.unwrap()
.begin_render_pass(
@ -489,17 +491,20 @@ fn main() {
framebuffers[image_index as usize].clone(),
)
},
SubpassContents::Inline,
Default::default(),
)
.unwrap()
.set_viewport(0, [viewport.clone()].into_iter().collect())
.unwrap()
.bind_pipeline_graphics(render_pipeline.clone())
.unwrap()
.bind_vertex_buffers(0, vertices)
.unwrap()
// 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()
.end_render_pass(Default::default())
.unwrap();
let command_buffer = builder.build().unwrap();

View File

@ -17,7 +17,7 @@ use vulkano::{
buffer::{Buffer, BufferContents, BufferCreateInfo, BufferUsage},
command_buffer::{
allocator::StandardCommandBufferAllocator, AutoCommandBufferBuilder, CommandBufferUsage,
RenderPassBeginInfo, SubpassContents,
RenderPassBeginInfo,
},
device::{
physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo,
@ -415,13 +415,16 @@ fn main() {
framebuffers[image_index as usize].clone(),
)
},
SubpassContents::Inline,
Default::default(),
)
.unwrap()
.set_viewport(0, [viewport.clone()].into_iter().collect())
.unwrap()
.bind_pipeline_graphics(pipeline.clone())
.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,
@ -429,7 +432,7 @@ fn main() {
0,
)
.unwrap()
.end_render_pass()
.end_render_pass(Default::default())
.unwrap();
let command_buffer = builder.build().unwrap();

View File

@ -175,8 +175,11 @@ impl FractalComputePipeline {
};
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();
let command_buffer = builder.build().unwrap();

View File

@ -228,15 +228,20 @@ impl PixelsDrawPipeline {
.into_iter()
.collect(),
)
.unwrap()
.bind_pipeline_graphics(self.pipeline.clone())
.unwrap()
.bind_descriptor_sets(
PipelineBindPoint::Graphics,
self.pipeline.layout().clone(),
0,
desc_set,
)
.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();
builder.build().unwrap()

View File

@ -12,7 +12,7 @@ use std::sync::Arc;
use vulkano::{
command_buffer::{
allocator::StandardCommandBufferAllocator, AutoCommandBufferBuilder, CommandBufferUsage,
RenderPassBeginInfo, SubpassContents,
RenderPassBeginInfo, SubpassBeginInfo, SubpassContents,
},
descriptor_set::allocator::StandardDescriptorSetAllocator,
device::Queue,
@ -111,7 +111,10 @@ impl RenderPassPlaceOverFrame {
clear_values: vec![Some([0.0; 4].into())],
..RenderPassBeginInfo::framebuffer(framebuffer)
},
SubpassContents::SecondaryCommandBuffers,
SubpassBeginInfo {
contents: SubpassContents::SecondaryCommandBuffers,
..Default::default()
},
)
.unwrap();
@ -122,7 +125,9 @@ impl RenderPassPlaceOverFrame {
command_buffer_builder.execute_commands(cb).unwrap();
// End render pass.
command_buffer_builder.end_render_pass().unwrap();
command_buffer_builder
.end_render_pass(Default::default())
.unwrap();
// Build command buffer.
let command_buffer = command_buffer_builder.build().unwrap();

View File

@ -67,7 +67,7 @@ use vulkano::{
buffer::{Buffer, BufferContents, BufferCreateInfo, BufferUsage},
command_buffer::{
allocator::StandardCommandBufferAllocator, AutoCommandBufferBuilder, CommandBufferUsage,
CopyImageToBufferInfo, PrimaryCommandBufferAbstract, RenderPassBeginInfo, SubpassContents,
CopyImageToBufferInfo, PrimaryCommandBufferAbstract, RenderPassBeginInfo,
},
device::{
physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo,
@ -394,15 +394,18 @@ fn main() {
clear_values: vec![Some([0.0, 0.0, 1.0, 1.0].into()), None],
..RenderPassBeginInfo::framebuffer(framebuffer)
},
SubpassContents::Inline,
Default::default(),
)
.unwrap()
.set_viewport(0, [viewport].into_iter().collect())
.unwrap()
.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()
.end_render_pass(Default::default())
.unwrap()
.copy_image_to_buffer(CopyImageToBufferInfo::image_buffer(image, buf.clone()))
.unwrap();

View File

@ -21,7 +21,7 @@ use vulkano::{
buffer::{Buffer, BufferContents, BufferCreateInfo, BufferUsage},
command_buffer::{
allocator::StandardCommandBufferAllocator, AutoCommandBufferBuilder, CommandBufferUsage,
RenderPassBeginInfo, SubpassContents,
RenderPassBeginInfo,
},
device::{
physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo,
@ -462,15 +462,18 @@ fn main() {
framebuffers[image_index as usize].clone(),
)
},
SubpassContents::Inline,
Default::default(),
)
.unwrap()
.set_viewport(0, [viewport.clone()].into_iter().collect())
.unwrap()
.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()
.end_render_pass(Default::default())
.unwrap();
let command_buffer = builder.build().unwrap();

View File

@ -201,8 +201,11 @@ impl GameOfLifeComputePipeline {
};
builder
.bind_pipeline_compute(self.compute_life_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();
}

View File

@ -224,15 +224,20 @@ impl PixelsDrawPipeline {
.into_iter()
.collect(),
)
.unwrap()
.bind_pipeline_graphics(self.pipeline.clone())
.unwrap()
.bind_descriptor_sets(
PipelineBindPoint::Graphics,
self.pipeline.layout().clone(),
0,
desc_set,
)
.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();
builder.build().unwrap()

View File

@ -12,7 +12,7 @@ use std::sync::Arc;
use vulkano::{
command_buffer::{
allocator::StandardCommandBufferAllocator, AutoCommandBufferBuilder, CommandBufferUsage,
RenderPassBeginInfo, SubpassContents,
RenderPassBeginInfo, SubpassBeginInfo, SubpassContents,
},
device::Queue,
format::Format,
@ -101,7 +101,10 @@ impl RenderPassPlaceOverFrame {
clear_values: vec![Some([0.0; 4].into())],
..RenderPassBeginInfo::framebuffer(framebuffer)
},
SubpassContents::SecondaryCommandBuffers,
SubpassBeginInfo {
contents: SubpassContents::SecondaryCommandBuffers,
..Default::default()
},
)
.unwrap();
@ -112,7 +115,9 @@ impl RenderPassPlaceOverFrame {
command_buffer_builder.execute_commands(cb).unwrap();
// End the render pass.
command_buffer_builder.end_render_pass().unwrap();
command_buffer_builder
.end_render_pass(Default::default())
.unwrap();
// Build the command buffer.
let command_buffer = command_buffer_builder.build().unwrap();

View File

@ -17,7 +17,7 @@ use vulkano::{
buffer::{Buffer, BufferContents, BufferCreateInfo, BufferUsage, Subbuffer},
command_buffer::{
allocator::StandardCommandBufferAllocator, AutoCommandBufferBuilder, BufferImageCopy,
CommandBufferUsage, CopyImageToBufferInfo, RenderPassBeginInfo, SubpassContents,
CommandBufferUsage, CopyImageToBufferInfo, RenderPassBeginInfo,
},
device::{
physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, Features,
@ -346,14 +346,16 @@ fn main() {
clear_values: vec![Some([0.0, 0.0, 1.0, 1.0].into())],
..RenderPassBeginInfo::framebuffer(framebuffer)
},
SubpassContents::Inline,
Default::default(),
)
.unwrap()
.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()
.end_render_pass(Default::default())
.unwrap();
// Copy the image layers to different buffers to save them as individual images to disk.

View File

@ -16,7 +16,7 @@ use vulkano::{
buffer::{Buffer, BufferContents, BufferCreateInfo, BufferUsage},
command_buffer::{
allocator::StandardCommandBufferAllocator, AutoCommandBufferBuilder, CommandBufferUsage,
RenderPassBeginInfo, SubpassContents,
RenderPassBeginInfo,
},
device::{
physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo,
@ -436,7 +436,9 @@ fn main() {
.reset_query_pool(query_pool.clone(), 0..3)
.unwrap()
.set_viewport(0, [viewport.clone()].into_iter().collect())
.unwrap()
.bind_pipeline_graphics(pipeline.clone())
.unwrap()
.begin_render_pass(
RenderPassBeginInfo {
clear_values: vec![Some([0.0, 0.0, 1.0, 1.0].into()), Some(1.0.into())],
@ -444,7 +446,7 @@ fn main() {
framebuffers[image_index as usize].clone(),
)
},
SubpassContents::Inline,
Default::default(),
)
.unwrap()
// Begin query 0, then draw the red triangle. Enabling the
@ -458,6 +460,7 @@ fn main() {
)
.unwrap()
.bind_vertex_buffers(0, triangle1.clone())
.unwrap()
.draw(triangle1.len() as u32, 1, 0, 0)
.unwrap()
// End query 0.
@ -467,6 +470,7 @@ fn main() {
.begin_query(query_pool.clone(), 1, QueryControlFlags::empty())
.unwrap()
.bind_vertex_buffers(0, triangle2.clone())
.unwrap()
.draw(triangle2.len() as u32, 1, 0, 0)
.unwrap()
.end_query(query_pool.clone(), 1)
@ -475,11 +479,12 @@ fn main() {
.begin_query(query_pool.clone(), 2, QueryControlFlags::empty())
.unwrap()
.bind_vertex_buffers(0, triangle3.clone())
.unwrap()
.draw(triangle3.len() as u32, 1, 0, 0)
.unwrap()
.end_query(query_pool.clone(), 2)
.unwrap()
.end_render_pass()
.end_render_pass(Default::default())
.unwrap();
}

View File

@ -191,13 +191,16 @@ fn main() {
.unwrap();
builder
.bind_pipeline_compute(pipeline.clone())
.unwrap()
.bind_descriptor_sets(
PipelineBindPoint::Compute,
pipeline.layout().clone(),
0,
set,
)
.unwrap()
.push_constants(pipeline.layout().clone(), 0, push_constants)
.unwrap()
.dispatch([1024, 1, 1])
.unwrap();
let command_buffer = builder.build().unwrap();

View File

@ -12,7 +12,7 @@ use vulkano::{
buffer::{Buffer, BufferContents, BufferCreateInfo, BufferUsage},
command_buffer::{
allocator::StandardCommandBufferAllocator, AutoCommandBufferBuilder, CommandBufferUsage,
CopyBufferToImageInfo, PrimaryCommandBufferAbstract, RenderPassBeginInfo, SubpassContents,
CopyBufferToImageInfo, PrimaryCommandBufferAbstract, RenderPassBeginInfo,
},
descriptor_set::{layout::DescriptorSetLayoutCreateFlags, WriteDescriptorSet},
device::{
@ -412,11 +412,13 @@ fn main() {
framebuffers[image_index as usize].clone(),
)
},
SubpassContents::Inline,
Default::default(),
)
.unwrap()
.set_viewport(0, [viewport.clone()].into_iter().collect())
.unwrap()
.bind_pipeline_graphics(pipeline.clone())
.unwrap()
.push_descriptor_set(
PipelineBindPoint::Graphics,
pipeline.layout().clone(),
@ -425,10 +427,12 @@ fn main() {
.into_iter()
.collect(),
)
.unwrap()
.bind_vertex_buffers(0, vertex_buffer.clone())
.unwrap()
.draw(vertex_buffer.len() as u32, 1, 0, 0)
.unwrap()
.end_render_pass()
.end_render_pass(Default::default())
.unwrap();
let command_buffer = builder.build().unwrap();

View File

@ -26,7 +26,7 @@ use vulkano::{
buffer::{Buffer, BufferContents, BufferCreateInfo, BufferUsage},
command_buffer::{
allocator::StandardCommandBufferAllocator, AutoCommandBufferBuilder, CommandBufferUsage,
RenderPassBeginInfo, SubpassContents,
RenderPassBeginInfo,
},
device::{
physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo,
@ -357,15 +357,18 @@ fn main() {
framebuffers[image_index as usize].clone(),
)
},
SubpassContents::Inline,
Default::default(),
)
.unwrap()
.set_viewport(0, [viewport.clone()].into_iter().collect())
.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()
.end_render_pass(Default::default())
.unwrap();
let command_buffer = builder.build().unwrap();

View File

@ -12,7 +12,7 @@ use vulkano::{
buffer::{Buffer, BufferContents, BufferCreateInfo, BufferUsage},
command_buffer::{
allocator::StandardCommandBufferAllocator, AutoCommandBufferBuilder, CommandBufferUsage,
CopyBufferToImageInfo, PrimaryCommandBufferAbstract, RenderPassBeginInfo, SubpassContents,
CopyBufferToImageInfo, PrimaryCommandBufferAbstract, RenderPassBeginInfo,
},
descriptor_set::{
allocator::StandardDescriptorSetAllocator, layout::DescriptorBindingFlags,
@ -547,21 +547,25 @@ fn main() {
framebuffers[image_index as usize].clone(),
)
},
SubpassContents::Inline,
Default::default(),
)
.unwrap()
.set_viewport(0, [viewport.clone()].into_iter().collect())
.unwrap()
.bind_pipeline_graphics(pipeline.clone())
.unwrap()
.bind_descriptor_sets(
PipelineBindPoint::Graphics,
pipeline.layout().clone(),
0,
set.clone(),
)
.unwrap()
.bind_vertex_buffers(0, vertex_buffer.clone())
.unwrap()
.draw(vertex_buffer.len() as u32, 1, 0, 0)
.unwrap()
.end_render_pass()
.end_render_pass(Default::default())
.unwrap();
let command_buffer = builder.build().unwrap();

View File

@ -186,12 +186,14 @@ fn main() {
})
.unwrap()
.bind_pipeline_compute(pipeline.clone())
.unwrap()
.bind_descriptor_sets(
PipelineBindPoint::Compute,
pipeline.layout().clone(),
0,
set,
)
.unwrap()
.dispatch([1024, 1, 1])
.unwrap();
let command_buffer = builder.build().unwrap();

View File

@ -177,12 +177,14 @@ fn main() {
.unwrap();
builder
.bind_pipeline_compute(pipeline.clone())
.unwrap()
.bind_descriptor_sets(
PipelineBindPoint::Compute,
pipeline.layout().clone(),
0,
set,
)
.unwrap()
.dispatch([1024, 1, 1])
.unwrap();
let command_buffer = builder.build().unwrap();

View File

@ -209,13 +209,16 @@ fn main() {
.unwrap();
builder
.bind_pipeline_compute(pipeline.clone())
.unwrap()
.bind_descriptor_sets(
PipelineBindPoint::Compute,
pipeline.layout().clone(),
0,
set,
)
.unwrap()
.push_constants(pipeline.layout().clone(), 0, parameters)
.unwrap()
.dispatch([1024, 1, 1])
.unwrap();
let command_buffer = builder.build().unwrap();

View File

@ -17,7 +17,7 @@ use vulkano::{
buffer::{Buffer, BufferContents, BufferCreateInfo, BufferUsage},
command_buffer::{
allocator::StandardCommandBufferAllocator, AutoCommandBufferBuilder, CommandBufferUsage,
CopyBufferInfo, PrimaryCommandBufferAbstract, RenderPassBeginInfo, SubpassContents,
CopyBufferInfo, PrimaryCommandBufferAbstract, RenderPassBeginInfo,
},
descriptor_set::{
allocator::StandardDescriptorSetAllocator, PersistentDescriptorSet, WriteDescriptorSet,
@ -582,14 +582,17 @@ fn main() {
builder
// Push constants for compute shader.
.push_constants(compute_pipeline.layout().clone(), 0, push_constants)
.unwrap()
// Perform compute operation to update particle positions.
.bind_pipeline_compute(compute_pipeline.clone())
.unwrap()
.bind_descriptor_sets(
PipelineBindPoint::Compute,
compute_pipeline.layout().clone(),
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.
@ -600,14 +603,16 @@ fn main() {
framebuffers[image_index as usize].clone(),
)
},
SubpassContents::Inline,
Default::default(),
)
.unwrap()
.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()
.end_render_pass(Default::default())
.unwrap();
let command_buffer = builder.build().unwrap();

View File

@ -177,12 +177,14 @@ fn main() {
.unwrap();
builder
.bind_pipeline_compute(pipeline.clone())
.unwrap()
.bind_descriptor_sets(
PipelineBindPoint::Compute,
pipeline.layout().clone(),
0,
set,
)
.unwrap()
.dispatch([1024, 1, 1])
.unwrap();
let command_buffer = builder.build().unwrap();

View File

@ -17,7 +17,7 @@ use vulkano::{
},
command_buffer::{
allocator::StandardCommandBufferAllocator, AutoCommandBufferBuilder, CommandBufferUsage,
RenderPassBeginInfo, SubpassContents,
RenderPassBeginInfo,
},
descriptor_set::{
allocator::StandardDescriptorSetAllocator, PersistentDescriptorSet, WriteDescriptorSet,
@ -382,21 +382,25 @@ fn main() {
framebuffers[image_index as usize].clone(),
)
},
SubpassContents::Inline,
Default::default(),
)
.unwrap()
.bind_pipeline_graphics(pipeline.clone())
.unwrap()
.bind_descriptor_sets(
PipelineBindPoint::Graphics,
pipeline.layout().clone(),
0,
set,
)
.unwrap()
.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()
.end_render_pass(Default::default())
.unwrap();
let command_buffer = builder.build().unwrap();

View File

@ -26,7 +26,7 @@ use vulkano::{
buffer::{Buffer, BufferContents, BufferCreateInfo, BufferUsage},
command_buffer::{
allocator::StandardCommandBufferAllocator, AutoCommandBufferBuilder, CommandBufferUsage,
RenderPassBeginInfo, SubpassContents,
RenderPassBeginInfo,
},
device::{
physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, Features,
@ -473,15 +473,18 @@ fn main() {
framebuffers[image_index as usize].clone(),
)
},
SubpassContents::Inline,
Default::default(),
)
.unwrap()
.set_viewport(0, [viewport.clone()].into_iter().collect())
.unwrap()
.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()
.end_render_pass(Default::default())
.unwrap();
let command_buffer = builder.build().unwrap();

View File

@ -12,7 +12,7 @@ use vulkano::{
buffer::{Buffer, BufferContents, BufferCreateInfo, BufferUsage},
command_buffer::{
allocator::StandardCommandBufferAllocator, AutoCommandBufferBuilder, CommandBufferUsage,
CopyBufferToImageInfo, PrimaryCommandBufferAbstract, RenderPassBeginInfo, SubpassContents,
CopyBufferToImageInfo, PrimaryCommandBufferAbstract, RenderPassBeginInfo,
},
descriptor_set::{
allocator::StandardDescriptorSetAllocator, PersistentDescriptorSet, WriteDescriptorSet,
@ -429,21 +429,25 @@ fn main() {
framebuffers[image_index as usize].clone(),
)
},
SubpassContents::Inline,
Default::default(),
)
.unwrap()
.set_viewport(0, [viewport.clone()].into_iter().collect())
.unwrap()
.bind_pipeline_graphics(pipeline.clone())
.unwrap()
.bind_descriptor_sets(
PipelineBindPoint::Graphics,
pipeline.layout().clone(),
0,
set.clone(),
)
.unwrap()
.bind_vertex_buffers(0, vertex_buffer.clone())
.unwrap()
.draw(vertex_buffer.len() as u32, 3, 0, 0)
.unwrap()
.end_render_pass()
.end_render_pass(Default::default())
.unwrap();
let command_buffer = builder.build().unwrap();

View File

@ -635,8 +635,11 @@ fn main() {
//
// TODO: Document state setting and how it affects subsequent draw commands.
.set_viewport(0, [viewport.clone()].into_iter().collect())
.unwrap()
.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()

View File

@ -21,7 +21,7 @@ use vulkano::{
buffer::{Buffer, BufferContents, BufferCreateInfo, BufferUsage},
command_buffer::{
allocator::StandardCommandBufferAllocator, AutoCommandBufferBuilder, CommandBufferUsage,
RenderPassBeginInfo, SubpassContents,
RenderPassBeginInfo, SubpassBeginInfo, SubpassContents,
},
device::{
physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo,
@ -618,24 +618,30 @@ fn main() {
framebuffers[image_index as usize].clone(),
)
},
// The contents of the first (and only) subpass. This can be either
// `Inline` or `SecondaryCommandBuffers`. The latter is a bit more advanced
// and is not covered here.
SubpassContents::Inline,
SubpassBeginInfo {
// The contents of the first (and only) subpass.
// This can be either `Inline` or `SecondaryCommandBuffers`.
// The latter is a bit more advanced and is not covered here.
contents: SubpassContents::Inline,
..Default::default()
},
)
.unwrap()
// We are now inside the first subpass of the render pass.
//
// TODO: Document state setting and how it affects subsequent draw commands.
.set_viewport(0, [viewport.clone()].into_iter().collect())
.unwrap()
.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()
// 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()
.end_render_pass(Default::default())
.unwrap();
// Finish building the command buffer by calling `build`.

View File

@ -129,7 +129,7 @@ fn write_descriptor_binding_requirements(
let image_scalar_type = match image_scalar_type {
Some(image_scalar_type) => {
let ident = format_ident!("{}", format!("{:?}", image_scalar_type));
quote! { Some(::vulkano::shader::ShaderScalarType::#ident) }
quote! { Some(::vulkano::format::NumericType::#ident) }
}
None => quote! { None },
};
@ -305,7 +305,7 @@ fn write_interface(interface: &ShaderInterface) -> TokenStream {
location: #location,
component: #component,
ty: ::vulkano::shader::ShaderInterfaceEntryType {
base_type: ::vulkano::shader::ShaderScalarType::#base_type,
base_type: ::vulkano::format::NumericType::#base_type,
num_components: #num_components,
num_elements: #num_elements,
is_64bit: #is_64bit,

View File

@ -53,9 +53,9 @@ struct FormatMember {
compression: Option<Ident>,
planes: Vec<Ident>,
texels_per_block: u8,
type_color: Option<Ident>,
type_depth: Option<Ident>,
type_stencil: Option<Ident>,
numeric_format_color: Option<Ident>,
numeric_format_depth: Option<Ident>,
numeric_format_stencil: Option<Ident>,
ycbcr_chroma_sampling: Option<Ident>,
type_std_array: Option<TokenStream>,
@ -182,31 +182,37 @@ fn formats_output(members: &[FormatMember]) -> TokenStream {
})
},
);
let type_color_items = members.iter().filter_map(
let numeric_format_color_items = members.iter().filter_map(
|FormatMember {
name, type_color, ..
name,
numeric_format_color,
..
}| {
type_color
numeric_format_color
.as_ref()
.map(|ty| quote! { Self::#name => Some(NumericType::#ty), })
.map(|ty| quote! { Self::#name => Some(NumericFormat::#ty), })
},
);
let type_depth_items = members.iter().filter_map(
let numeric_format_depth_items = members.iter().filter_map(
|FormatMember {
name, type_depth, ..
name,
numeric_format_depth,
..
}| {
type_depth
numeric_format_depth
.as_ref()
.map(|ty| quote! { Self::#name => Some(NumericType::#ty), })
.map(|ty| quote! { Self::#name => Some(NumericFormat::#ty), })
},
);
let type_stencil_items = members.iter().filter_map(
let numeric_format_stencil_items = members.iter().filter_map(
|FormatMember {
name, type_stencil, ..
name,
numeric_format_stencil,
..
}| {
type_stencil
numeric_format_stencil
.as_ref()
.map(|ty| quote! { Self::#name => Some(NumericType::#ty), })
.map(|ty| quote! { Self::#name => Some(NumericFormat::#ty), })
},
);
let ycbcr_chroma_sampling_items = members.iter().filter_map(
@ -432,29 +438,29 @@ fn formats_output(members: &[FormatMember]) -> TokenStream {
}
}
/// Returns the numeric data type of the color aspect of this format. Returns `None`
/// Returns the numeric format of the color aspect of this format. Returns `None`
/// for depth/stencil formats.
pub fn type_color(self) -> Option<NumericType> {
pub fn numeric_format_color(self) -> Option<NumericFormat> {
match self {
#(#type_color_items)*
#(#numeric_format_color_items)*
_ => None,
}
}
/// Returns the numeric data type of the depth aspect of this format. Returns `None`
/// Returns the numeric format of the depth aspect of this format. Returns `None`
/// color and stencil-only formats.
pub fn type_depth(self) -> Option<NumericType> {
pub fn numeric_format_depth(self) -> Option<NumericFormat> {
match self {
#(#type_depth_items)*
#(#numeric_format_depth_items)*
_ => None,
}
}
/// Returns the numeric data type of the stencil aspect of this format. Returns `None`
/// Returns the numeric format of the stencil aspect of this format. Returns `None`
/// for color and depth-only formats.
pub fn type_stencil(self) -> Option<NumericType> {
pub fn numeric_format_stencil(self) -> Option<NumericFormat> {
match self {
#(#type_stencil_items)*
#(#numeric_format_stencil_items)*
_ => None,
}
}
@ -606,9 +612,9 @@ fn formats_members(
compression: None,
planes: vec![],
texels_per_block: 0,
type_color: None,
type_depth: None,
type_stencil: None,
numeric_format_color: None,
numeric_format_depth: None,
numeric_format_stencil: None,
ycbcr_chroma_sampling: None,
type_std_array: None,
@ -655,9 +661,9 @@ fn formats_members(
.map(|c| format_ident!("{}", c.replace(' ', "_"))),
planes: vec![],
texels_per_block: format.texelsPerBlock,
type_color: None,
type_depth: None,
type_stencil: None,
numeric_format_color: None,
numeric_format_depth: None,
numeric_format_stencil: None,
ycbcr_chroma_sampling: None,
type_std_array: None,
@ -684,32 +690,32 @@ fn formats_members(
"R" => {
member.aspect_color = true;
member.components[0] += bits;
member.type_color = Some(ty);
member.numeric_format_color = Some(ty);
}
"G" => {
member.aspect_color = true;
member.components[1] += bits;
member.type_color = Some(ty);
member.numeric_format_color = Some(ty);
}
"B" => {
member.aspect_color = true;
member.components[2] += bits;
member.type_color = Some(ty);
member.numeric_format_color = Some(ty);
}
"A" => {
member.aspect_color = true;
member.components[3] += bits;
member.type_color = Some(ty);
member.numeric_format_color = Some(ty);
}
"D" => {
member.aspect_depth = true;
member.components[0] += bits;
member.type_depth = Some(ty);
member.numeric_format_depth = Some(ty);
}
"S" => {
member.aspect_stencil = true;
member.components[1] += bits;
member.type_stencil = Some(ty);
member.numeric_format_stencil = Some(ty);
}
_ => {
panic!("Unknown component type {} on format {}", name, format.name)
@ -752,7 +758,7 @@ fn formats_members(
}
};
if let (Some(numeric_type), true) = (&member.type_color, member.planes.is_empty()) {
if let (Some(numeric_type), true) = (&member.numeric_format_color, member.planes.is_empty()) {
if format.compressed.is_some() {
member.type_std_array = Some({
let block_size = Literal::usize_unsuffixed(format.blockSize as usize);

View File

@ -24,7 +24,7 @@ use crate::{
SecondaryCommandBufferResourcesUsage, SubpassContents,
},
descriptor_set::{DescriptorSetResources, DescriptorSetWithOffsets},
device::{Device, DeviceOwned, QueueFamilyProperties},
device::{Device, DeviceOwned},
image::{view::ImageView, Image, ImageAspects, ImageLayout, ImageSubresourceRange},
pipeline::{
graphics::{
@ -42,7 +42,7 @@ use crate::{
range_set::RangeSet,
render_pass::{Framebuffer, Subpass},
sync::{
AccessFlags, BufferMemoryBarrier, DependencyInfo, ImageMemoryBarrier,
AccessFlags, BufferMemoryBarrier, DependencyFlags, DependencyInfo, ImageMemoryBarrier,
PipelineStageAccessFlags, PipelineStages,
},
DeviceSize, Validated, ValidationError, VulkanError,
@ -293,7 +293,13 @@ where
if let Some(barriers) = barriers.remove(&command_index) {
for dependency_info in barriers {
unsafe {
self.inner.pipeline_barrier(&dependency_info);
#[cfg(debug_assertions)]
self.inner
.pipeline_barrier(&dependency_info)
.expect("bug in Vulkano");
#[cfg(not(debug_assertions))]
self.inner.pipeline_barrier_unchecked(&dependency_info);
}
}
}
@ -305,7 +311,13 @@ where
if let Some(final_barriers) = barriers.remove(&final_barrier_index) {
for dependency_info in final_barriers {
unsafe {
self.inner.pipeline_barrier(&dependency_info);
#[cfg(debug_assertions)]
self.inner
.pipeline_barrier(&dependency_info)
.expect("bug in Vulkano");
#[cfg(not(debug_assertions))]
self.inner.pipeline_barrier_unchecked(&dependency_info);
}
}
}
@ -402,11 +414,6 @@ impl<L, A> AutoCommandBufferBuilder<L, A>
where
A: CommandBufferAllocator,
{
#[inline]
pub(in crate::command_buffer) fn queue_family_properties(&self) -> &QueueFamilyProperties {
self.inner.queue_family_properties()
}
pub(in crate::command_buffer) fn add_command(
&mut self,
name: &'static str,
@ -490,7 +497,10 @@ impl AutoSyncState {
level,
command_index: 0,
pending_barrier: DependencyInfo::default(),
pending_barrier: DependencyInfo {
dependency_flags: DependencyFlags::BY_REGION,
..DependencyInfo::default()
},
barriers: Default::default(),
first_unflushed: 0,
latest_render_pass_enter: has_inherited_render_pass.then_some(0),
@ -517,7 +527,10 @@ impl AutoSyncState {
// Add one last barrier to transition images to their desired final layout.
if self.level == CommandBufferLevel::Primary {
let mut final_barrier = DependencyInfo::default();
let mut final_barrier = DependencyInfo {
dependency_flags: DependencyFlags::BY_REGION,
..DependencyInfo::default()
};
for (image, range_map) in self.images.iter_mut() {
for (range, state) in range_map

View File

@ -73,8 +73,8 @@ pub(in crate::command_buffer) use self::builder::{
use super::{
allocator::{CommandBufferAllocator, StandardCommandBufferAllocator},
sys::{UnsafeCommandBuffer, UnsafeCommandBufferBuilder},
CommandBufferExecError, CommandBufferInheritanceInfo, CommandBufferResourcesUsage,
CommandBufferState, CommandBufferUsage, PrimaryCommandBufferAbstract, ResourceInCommand,
CommandBufferInheritanceInfo, CommandBufferResourcesUsage, CommandBufferState,
CommandBufferUsage, PrimaryCommandBufferAbstract, ResourceInCommand,
SecondaryCommandBufferAbstract, SecondaryCommandBufferResourcesUsage, SecondaryResourceUseRef,
};
use crate::{
@ -82,7 +82,7 @@ use crate::{
device::{Device, DeviceOwned},
image::{Image, ImageLayout, ImageSubresourceRange},
sync::PipelineStageAccessFlags,
DeviceSize, VulkanObject,
DeviceSize, ValidationError, VulkanObject,
};
use parking_lot::{Mutex, MutexGuard};
use std::{
@ -187,20 +187,34 @@ where
self.inner.inheritance_info().as_ref().unwrap()
}
fn lock_record(&self) -> Result<(), CommandBufferExecError> {
fn lock_record(&self) -> Result<(), Box<ValidationError>> {
match self.submit_state {
SubmitState::OneTime {
ref already_submitted,
} => {
let was_already_submitted = already_submitted.swap(true, Ordering::SeqCst);
if was_already_submitted {
return Err(CommandBufferExecError::OneTimeSubmitAlreadySubmitted);
return Err(Box::new(ValidationError {
problem: "the command buffer was created with the \
`CommandBufferUsage::OneTimeSubmit` usage, but \
it was already submitted before"
.into(),
// vuids?
..Default::default()
}));
}
}
SubmitState::ExclusiveUse { ref in_use } => {
let already_in_use = in_use.swap(true, Ordering::SeqCst);
if already_in_use {
return Err(CommandBufferExecError::ExclusiveAlreadyInUse);
return Err(Box::new(ValidationError {
problem: "the command buffer was created with the \
`CommandBufferUsage::MultipleSubmit` usage, but \
it is currently being executed"
.into(),
// vuids?
..Default::default()
}));
}
}
SubmitState::Concurrent => (),
@ -308,8 +322,7 @@ mod tests {
buffer::{Buffer, BufferCreateInfo, BufferUsage},
command_buffer::{
allocator::StandardCommandBufferAllocator, AutoCommandBufferBuilder, BufferCopy,
CommandBufferExecError, CommandBufferUsage, CopyBufferInfoTyped, CopyError,
ExecuteCommandsError, PrimaryCommandBufferAbstract,
CommandBufferUsage, CopyBufferInfoTyped, PrimaryCommandBufferAbstract,
},
descriptor_set::{
allocator::StandardDescriptorSetAllocator,
@ -458,12 +471,7 @@ mod tests {
// Recording the same non-concurrent secondary command buffer twice into the same
// primary is an error.
assert!(matches!(
builder.execute_commands(secondary.clone()),
Err(ExecuteCommandsError::ExecError(
CommandBufferExecError::ExclusiveAlreadyInUse
))
));
assert!(builder.execute_commands(secondary.clone()).is_err());
}
{
@ -485,12 +493,7 @@ mod tests {
// Recording the same non-concurrent secondary command buffer into multiple
// primaries is an error.
assert!(matches!(
builder.execute_commands(secondary.clone()),
Err(ExecuteCommandsError::ExecError(
CommandBufferExecError::ExclusiveAlreadyInUse
))
));
assert!(builder.execute_commands(secondary.clone()).is_err());
std::mem::drop(cb1);
@ -582,8 +585,8 @@ mod tests {
)
.unwrap();
assert!(matches!(
builder.copy_buffer(CopyBufferInfoTyped {
assert!(builder
.copy_buffer(CopyBufferInfoTyped {
regions: [BufferCopy {
src_offset: 0,
dst_offset: 1,
@ -592,12 +595,8 @@ mod tests {
}]
.into(),
..CopyBufferInfoTyped::buffers(source.clone(), source)
}),
Err(CopyError::OverlappingRegions {
src_region_index: 0,
dst_region_index: 0,
})
));
.is_err());
}
#[test]

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -14,13 +14,9 @@ use crate::{
},
device::{DeviceOwned, QueueFlags},
instance::debug::DebugUtilsLabel,
Requires, RequiresAllOf, RequiresOneOf, VulkanObject,
};
use std::{
error::Error,
ffi::CString,
fmt::{Display, Error as FmtError, Formatter},
Requires, RequiresAllOf, RequiresOneOf, ValidationError, VulkanObject,
};
use std::ffi::CString;
/// # Commands for debugging.
///
@ -35,43 +31,17 @@ where
pub fn begin_debug_utils_label(
&mut self,
label_info: DebugUtilsLabel,
) -> Result<&mut Self, DebugUtilsError> {
) -> Result<&mut Self, Box<ValidationError>> {
self.validate_begin_debug_utils_label(&label_info)?;
unsafe {
self.begin_debug_utils_label_unchecked(label_info);
}
Ok(self)
unsafe { Ok(self.begin_debug_utils_label_unchecked(label_info)) }
}
fn validate_begin_debug_utils_label(
&self,
_label_info: &DebugUtilsLabel,
) -> Result<(), DebugUtilsError> {
if !self
.device()
.instance()
.enabled_extensions()
.ext_debug_utils
{
return Err(DebugUtilsError::RequirementNotMet {
required_for: "`AutoCommandBufferBuilder::begin_debug_utils_label`",
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::InstanceExtension(
"ext_debug_utils",
)])]),
});
}
let queue_family_properties = self.queue_family_properties();
// VUID-vkCmdBeginDebugUtilsLabelEXT-commandBuffer-cmdpool
if !queue_family_properties
.queue_flags
.intersects(QueueFlags::GRAPHICS | QueueFlags::COMPUTE)
{
return Err(DebugUtilsError::NotSupportedByQueueFamily);
}
label_info: &DebugUtilsLabel,
) -> Result<(), Box<ValidationError>> {
self.inner.validate_begin_debug_utils_label(label_info)?;
Ok(())
}
@ -85,7 +55,7 @@ where
"begin_debug_utils_label",
Default::default(),
move |out: &mut UnsafeCommandBufferBuilder<A>| {
out.begin_debug_utils_label(&label_info);
out.begin_debug_utils_label_unchecked(&label_info);
},
);
@ -99,44 +69,18 @@ where
/// - When submitting the command buffer, there must be an outstanding command buffer label
/// region begun with `begin_debug_utils_label` in the queue, either within this command
/// buffer or a previously submitted one.
pub unsafe fn end_debug_utils_label(&mut self) -> Result<&mut Self, DebugUtilsError> {
pub unsafe fn end_debug_utils_label(&mut self) -> Result<&mut Self, Box<ValidationError>> {
self.validate_end_debug_utils_label()?;
self.end_debug_utils_label_unchecked();
Ok(self)
Ok(self.end_debug_utils_label_unchecked())
}
fn validate_end_debug_utils_label(&self) -> Result<(), DebugUtilsError> {
if !self
.device()
.instance()
.enabled_extensions()
.ext_debug_utils
{
return Err(DebugUtilsError::RequirementNotMet {
required_for: "`AutoCommandBufferBuilder::end_debug_utils_label`",
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::InstanceExtension(
"ext_debug_utils",
)])]),
});
}
let queue_family_properties = self.queue_family_properties();
// VUID-vkCmdEndDebugUtilsLabelEXT-commandBuffer-cmdpool
if !queue_family_properties
.queue_flags
.intersects(QueueFlags::GRAPHICS | QueueFlags::COMPUTE)
{
return Err(DebugUtilsError::NotSupportedByQueueFamily);
}
fn validate_end_debug_utils_label(&self) -> Result<(), Box<ValidationError>> {
self.inner.validate_end_debug_utils_label()?;
// TODO:
// VUID-vkCmdEndDebugUtilsLabelEXT-commandBuffer-01912
// TODO: not checked, so unsafe for now
// VUID-vkCmdEndDebugUtilsLabelEXT-commandBuffer-01913
// TODO: not checked, so unsafe for now
Ok(())
}
@ -147,7 +91,7 @@ where
"end_debug_utils_label",
Default::default(),
move |out: &mut UnsafeCommandBufferBuilder<A>| {
out.end_debug_utils_label();
out.end_debug_utils_label_unchecked();
},
);
@ -158,43 +102,17 @@ where
pub fn insert_debug_utils_label(
&mut self,
label_info: DebugUtilsLabel,
) -> Result<&mut Self, DebugUtilsError> {
) -> Result<&mut Self, Box<ValidationError>> {
self.validate_insert_debug_utils_label(&label_info)?;
unsafe {
self.insert_debug_utils_label_unchecked(label_info);
}
Ok(self)
unsafe { Ok(self.insert_debug_utils_label_unchecked(label_info)) }
}
fn validate_insert_debug_utils_label(
&self,
_label_info: &DebugUtilsLabel,
) -> Result<(), DebugUtilsError> {
if !self
.device()
.instance()
.enabled_extensions()
.ext_debug_utils
{
return Err(DebugUtilsError::RequirementNotMet {
required_for: "`AutoCommandBufferBuilder::insert_debug_utils_label`",
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::InstanceExtension(
"ext_debug_utils",
)])]),
});
}
let queue_family_properties = self.queue_family_properties();
// VUID-vkCmdInsertDebugUtilsLabelEXT-commandBuffer-cmdpool
if !queue_family_properties
.queue_flags
.intersects(QueueFlags::GRAPHICS | QueueFlags::COMPUTE)
{
return Err(DebugUtilsError::NotSupportedByQueueFamily);
}
label_info: &DebugUtilsLabel,
) -> Result<(), Box<ValidationError>> {
self.inner.validate_insert_debug_utils_label(label_info)?;
Ok(())
}
@ -208,7 +126,7 @@ where
"insert_debug_utils_label",
Default::default(),
move |out: &mut UnsafeCommandBufferBuilder<A>| {
out.insert_debug_utils_label(&label_info);
out.insert_debug_utils_label_unchecked(&label_info);
},
);
@ -220,13 +138,55 @@ impl<A> UnsafeCommandBufferBuilder<A>
where
A: CommandBufferAllocator,
{
/// Calls `vkCmdBeginDebugUtilsLabelEXT` on the builder.
///
/// # Safety
/// The command pool that this command buffer was allocated from must support graphics or
/// compute operations
#[inline]
pub unsafe fn begin_debug_utils_label(&mut self, label_info: &DebugUtilsLabel) -> &mut Self {
pub unsafe fn begin_debug_utils_label(
&mut self,
label_info: &DebugUtilsLabel,
) -> Result<&mut Self, Box<ValidationError>> {
self.validate_begin_debug_utils_label(label_info)?;
Ok(self.begin_debug_utils_label_unchecked(label_info))
}
fn validate_begin_debug_utils_label(
&self,
_label_info: &DebugUtilsLabel,
) -> Result<(), Box<ValidationError>> {
if !self
.device()
.instance()
.enabled_extensions()
.ext_debug_utils
{
return Err(Box::new(ValidationError {
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::InstanceExtension(
"ext_debug_utils",
)])]),
..Default::default()
}));
}
if !self
.queue_family_properties()
.queue_flags
.intersects(QueueFlags::GRAPHICS | QueueFlags::COMPUTE)
{
return Err(Box::new(ValidationError {
problem: "the queue family of the command buffer does not support \
graphics or compute operations"
.into(),
vuids: &["VUID-vkCmdBeginDebugUtilsLabelEXT-commandBuffer-cmdpool"],
..Default::default()
}));
}
Ok(())
}
#[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
pub unsafe fn begin_debug_utils_label_unchecked(
&mut self,
label_info: &DebugUtilsLabel,
) -> &mut Self {
let &DebugUtilsLabel {
ref label_name,
color,
@ -246,26 +206,101 @@ where
self
}
/// Calls `vkCmdEndDebugUtilsLabelEXT` on the builder.
///
/// # Safety
/// There must be an outstanding `vkCmdBeginDebugUtilsLabelEXT` command prior to the
/// `vkQueueEndDebugUtilsLabelEXT` on the queue tha `CommandBuffer` is submitted to.
#[inline]
pub unsafe fn end_debug_utils_label(&mut self) -> &mut Self {
pub unsafe fn end_debug_utils_label(&mut self) -> Result<&mut Self, Box<ValidationError>> {
self.validate_end_debug_utils_label()?;
Ok(self.end_debug_utils_label_unchecked())
}
fn validate_end_debug_utils_label(&self) -> Result<(), Box<ValidationError>> {
if !self
.device()
.instance()
.enabled_extensions()
.ext_debug_utils
{
return Err(Box::new(ValidationError {
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::InstanceExtension(
"ext_debug_utils",
)])]),
..Default::default()
}));
}
if !self
.queue_family_properties()
.queue_flags
.intersects(QueueFlags::GRAPHICS | QueueFlags::COMPUTE)
{
return Err(Box::new(ValidationError {
problem: "the queue family of the command buffer does not support \
graphics or compute operations"
.into(),
vuids: &["VUID-vkCmdEndDebugUtilsLabelEXT-commandBuffer-cmdpool"],
..Default::default()
}));
}
Ok(())
}
#[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
pub unsafe fn end_debug_utils_label_unchecked(&mut self) -> &mut Self {
let fns = self.device().instance().fns();
(fns.ext_debug_utils.cmd_end_debug_utils_label_ext)(self.handle());
self
}
/// Calls `vkCmdInsertDebugUtilsLabelEXT` on the builder.
///
/// # Safety
/// The command pool that this command buffer was allocated from must support graphics or
/// compute operations
#[inline]
pub unsafe fn insert_debug_utils_label(&mut self, label_info: &DebugUtilsLabel) -> &mut Self {
pub unsafe fn insert_debug_utils_label(
&mut self,
label_info: &DebugUtilsLabel,
) -> Result<&mut Self, Box<ValidationError>> {
self.validate_insert_debug_utils_label(label_info)?;
Ok(self.insert_debug_utils_label_unchecked(label_info))
}
fn validate_insert_debug_utils_label(
&self,
_label_info: &DebugUtilsLabel,
) -> Result<(), Box<ValidationError>> {
if !self
.device()
.instance()
.enabled_extensions()
.ext_debug_utils
{
return Err(Box::new(ValidationError {
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::InstanceExtension(
"ext_debug_utils",
)])]),
..Default::default()
}));
}
if !self
.queue_family_properties()
.queue_flags
.intersects(QueueFlags::GRAPHICS | QueueFlags::COMPUTE)
{
return Err(Box::new(ValidationError {
problem: "the queue family of the command buffer does not support \
graphics or compute operations"
.into(),
vuids: &["VUID-vkCmdInsertDebugUtilsLabelEXT-commandBuffer-cmdpool"],
..Default::default()
}));
}
Ok(())
}
#[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
pub unsafe fn insert_debug_utils_label_unchecked(
&mut self,
label_info: &DebugUtilsLabel,
) -> &mut Self {
let &DebugUtilsLabel {
ref label_name,
color,
@ -285,35 +320,3 @@ where
self
}
}
/// Error that can happen when recording a debug utils command.
#[derive(Clone, Debug)]
pub enum DebugUtilsError {
RequirementNotMet {
required_for: &'static str,
requires_one_of: RequiresOneOf,
},
/// The queue family doesn't allow this operation.
NotSupportedByQueueFamily,
}
impl Error for DebugUtilsError {}
impl Display for DebugUtilsError {
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
match self {
Self::RequirementNotMet {
required_for,
requires_one_of,
} => write!(
f,
"a requirement was not met for: {}; requires one of: {}",
required_for, requires_one_of,
),
Self::NotSupportedByQueueFamily => {
write!(f, "the queue family doesn't allow this operation")
}
}
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -9,12 +9,12 @@
use crate::{
command_buffer::{allocator::CommandBufferAllocator, sys::UnsafeCommandBufferBuilder},
device::DeviceOwned,
device::{DeviceOwned, QueueFlags},
sync::{
event::Event, BufferMemoryBarrier, DependencyFlags, DependencyInfo, ImageMemoryBarrier,
MemoryBarrier, PipelineStages,
},
Version, VulkanObject,
Requires, RequiresAllOf, RequiresOneOf, ValidationError, Version, VulkanObject,
};
use smallvec::SmallVec;
use std::{ptr, sync::Arc};
@ -23,23 +23,199 @@ impl<A> UnsafeCommandBufferBuilder<A>
where
A: CommandBufferAllocator,
{
#[inline]
pub unsafe fn pipeline_barrier(&mut self, dependency_info: &DependencyInfo) -> &mut Self {
pub unsafe fn pipeline_barrier(
&mut self,
dependency_info: &DependencyInfo,
) -> Result<&mut Self, Box<ValidationError>> {
self.validate_pipeline_barrier(dependency_info)?;
Ok(self.pipeline_barrier_unchecked(dependency_info))
}
fn validate_pipeline_barrier(
&self,
dependency_info: &DependencyInfo,
) -> Result<(), Box<ValidationError>> {
let queue_family_properties = self.queue_family_properties();
if !queue_family_properties.queue_flags.intersects(
QueueFlags::TRANSFER
| QueueFlags::GRAPHICS
| QueueFlags::COMPUTE
| QueueFlags::VIDEO_DECODE
| QueueFlags::VIDEO_ENCODE,
) {
return Err(Box::new(ValidationError {
problem: "the queue family of the command buffer does not support \
transfer, graphics, compute, video decode or video encode operations"
.into(),
vuids: &["VUID-vkCmdPipelineBarrier2-commandBuffer-cmdpool"],
..Default::default()
}));
}
dependency_info
.validate(self.device())
.map_err(|err| err.add_context("dependency_info"))?;
let &DependencyInfo {
dependency_flags: _,
ref memory_barriers,
ref buffer_memory_barriers,
ref image_memory_barriers,
_ne,
} = dependency_info;
let supported_pipeline_stages = PipelineStages::from(queue_family_properties.queue_flags);
for (barrier_index, memory_barrier) in memory_barriers.iter().enumerate() {
let &MemoryBarrier {
src_stages,
src_access: _,
dst_stages,
dst_access: _,
_ne: _,
} = memory_barrier;
if !supported_pipeline_stages.contains(src_stages) {
return Err(Box::new(ValidationError {
context: format!(
"dependency_info.memory_barriers[{}].src_stages",
barrier_index
)
.into(),
problem: "contains stages that are not supported by the queue family of the \
command buffer"
.into(),
vuids: &["VUID-vkCmdPipelineBarrier2-srcStageMask-03849"],
..Default::default()
}));
}
if !supported_pipeline_stages.contains(dst_stages) {
return Err(Box::new(ValidationError {
context: format!(
"dependency_info.memory_barriers[{}].dst_stages",
barrier_index
)
.into(),
problem: "contains stages that are not supported by the queue family of the \
command buffer"
.into(),
vuids: &["VUID-vkCmdPipelineBarrier2-dstStageMask-03850"],
..Default::default()
}));
}
}
for (barrier_index, buffer_memory_barrier) in buffer_memory_barriers.iter().enumerate() {
let &BufferMemoryBarrier {
src_stages,
src_access: _,
dst_stages,
dst_access: _,
queue_family_ownership_transfer: _,
buffer: _,
range: _,
_ne: _,
} = buffer_memory_barrier;
if !supported_pipeline_stages.contains(src_stages) {
return Err(Box::new(ValidationError {
context: format!(
"dependency_info.buffer_memory_barriers[{}].src_stages",
barrier_index
)
.into(),
problem: "contains stages that are not supported by the queue family of the \
command buffer"
.into(),
vuids: &["VUID-vkCmdPipelineBarrier2-srcStageMask-03849"],
..Default::default()
}));
}
if !supported_pipeline_stages.contains(dst_stages) {
return Err(Box::new(ValidationError {
context: format!(
"dependency_info.buffer_memory_barriers[{}].dst_stages",
barrier_index
)
.into(),
problem: "contains stages that are not supported by the queue family of the \
command buffer"
.into(),
vuids: &["VUID-vkCmdPipelineBarrier2-dstStageMask-03850"],
..Default::default()
}));
}
}
for (barrier_index, image_memory_barrier) in image_memory_barriers.iter().enumerate() {
let &ImageMemoryBarrier {
src_stages,
src_access: _,
dst_stages,
dst_access: _,
old_layout: _,
new_layout: _,
queue_family_ownership_transfer: _,
image: _,
subresource_range: _,
_ne: _,
} = image_memory_barrier;
if !supported_pipeline_stages.contains(src_stages) {
return Err(Box::new(ValidationError {
context: format!(
"dependency_info.image_memory_barriers[{}].src_stages",
barrier_index
)
.into(),
problem: "contains stages that are not supported by the queue family of the \
command buffer"
.into(),
vuids: &["VUID-vkCmdPipelineBarrier2-srcStageMask-03849"],
..Default::default()
}));
}
if !supported_pipeline_stages.contains(dst_stages) {
return Err(Box::new(ValidationError {
context: format!(
"dependency_info.image_memory_barriers[{}].dst_stages",
barrier_index
)
.into(),
problem: "contains stages that are not supported by the queue family of the \
command buffer"
.into(),
vuids: &["VUID-vkCmdPipelineBarrier2-dstStageMask-03850"],
..Default::default()
}));
}
}
Ok(())
}
#[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
pub unsafe fn pipeline_barrier_unchecked(
&mut self,
dependency_info: &DependencyInfo,
) -> &mut Self {
if dependency_info.is_empty() {
return self;
}
let &DependencyInfo {
mut dependency_flags,
dependency_flags,
ref memory_barriers,
ref buffer_memory_barriers,
ref image_memory_barriers,
_ne: _,
} = dependency_info;
// TODO: Is this needed?
dependency_flags |= DependencyFlags::BY_REGION;
if self.device().enabled_features().synchronization2 {
let memory_barriers_vk: SmallVec<[_; 2]> = memory_barriers
.iter()
@ -287,12 +463,200 @@ where
self
}
/// Calls `vkCmdSetEvent` on the builder.
#[inline]
pub unsafe fn set_event(
&mut self,
event: &Event,
dependency_info: &DependencyInfo,
) -> Result<&mut Self, Box<ValidationError>> {
self.validate_set_event(event, dependency_info)?;
Ok(self.set_event_unchecked(event, dependency_info))
}
fn validate_set_event(
&self,
event: &Event,
dependency_info: &DependencyInfo,
) -> Result<(), Box<ValidationError>> {
let queue_family_properties = self.queue_family_properties();
if !queue_family_properties.queue_flags.intersects(
QueueFlags::GRAPHICS
| QueueFlags::COMPUTE
| QueueFlags::VIDEO_DECODE
| QueueFlags::VIDEO_ENCODE,
) {
return Err(Box::new(ValidationError {
problem: "the queue family of the command buffer does not support \
graphics, compute, video decode or video encode operations"
.into(),
vuids: &["VUID-vkCmdSetEvent2-commandBuffer-cmdpool"],
..Default::default()
}));
}
// VUID-vkCmdSetEvent2-commonparent
assert_eq!(self.device(), event.device());
dependency_info
.validate(self.device())
.map_err(|err| err.add_context("dependency_info"))?;
let &DependencyInfo {
dependency_flags,
ref memory_barriers,
ref buffer_memory_barriers,
ref image_memory_barriers,
_ne,
} = dependency_info;
if !dependency_flags.is_empty() {
return Err(Box::new(ValidationError {
context: "dependency_info.dependency_flags".into(),
problem: "is not empty".into(),
vuids: &["VUID-vkCmdSetEvent2-dependencyFlags-03825"],
..Default::default()
}));
}
let supported_pipeline_stages = PipelineStages::from(queue_family_properties.queue_flags);
for (barrier_index, memory_barrier) in memory_barriers.iter().enumerate() {
let &MemoryBarrier {
src_stages,
src_access: _,
dst_stages,
dst_access: _,
_ne: _,
} = memory_barrier;
if !supported_pipeline_stages.contains(src_stages) {
return Err(Box::new(ValidationError {
context: format!(
"dependency_info.memory_barriers[{}].src_stages",
barrier_index
)
.into(),
problem: "contains stages that are not supported by the queue family of the \
command buffer"
.into(),
vuids: &["VUID-vkCmdSetEvent2-srcStageMask-03827"],
..Default::default()
}));
}
if !supported_pipeline_stages.contains(dst_stages) {
return Err(Box::new(ValidationError {
context: format!(
"dependency_info.memory_barriers[{}].dst_stages",
barrier_index
)
.into(),
problem: "contains stages that are not supported by the queue family of the \
command buffer"
.into(),
vuids: &["VUID-vkCmdSetEvent2-dstStageMask-03828"],
..Default::default()
}));
}
}
for (barrier_index, buffer_memory_barrier) in buffer_memory_barriers.iter().enumerate() {
let &BufferMemoryBarrier {
src_stages,
src_access: _,
dst_stages,
dst_access: _,
queue_family_ownership_transfer: _,
buffer: _,
range: _,
_ne: _,
} = buffer_memory_barrier;
if !supported_pipeline_stages.contains(src_stages) {
return Err(Box::new(ValidationError {
context: format!(
"dependency_info.buffer_memory_barriers[{}].src_stages",
barrier_index
)
.into(),
problem: "contains stages that are not supported by the queue family of the \
command buffer"
.into(),
vuids: &["VUID-vkCmdSetEvent2-srcStageMask-03827"],
..Default::default()
}));
}
if !supported_pipeline_stages.contains(dst_stages) {
return Err(Box::new(ValidationError {
context: format!(
"dependency_info.buffer_memory_barriers[{}].dst_stages",
barrier_index
)
.into(),
problem: "contains stages that are not supported by the queue family of the \
command buffer"
.into(),
vuids: &["VUID-vkCmdSetEvent2-dstStageMask-03828"],
..Default::default()
}));
}
}
for (barrier_index, image_memory_barrier) in image_memory_barriers.iter().enumerate() {
let &ImageMemoryBarrier {
src_stages,
src_access: _,
dst_stages,
dst_access: _,
old_layout: _,
new_layout: _,
queue_family_ownership_transfer: _,
image: _,
subresource_range: _,
_ne: _,
} = image_memory_barrier;
if !supported_pipeline_stages.contains(src_stages) {
return Err(Box::new(ValidationError {
context: format!(
"dependency_info.image_memory_barriers[{}].src_stages",
barrier_index
)
.into(),
problem: "contains stages that are not supported by the queue family of the \
command buffer"
.into(),
vuids: &["VUID-vkCmdSetEvent2-srcStageMask-03827"],
..Default::default()
}));
}
if !supported_pipeline_stages.contains(dst_stages) {
return Err(Box::new(ValidationError {
context: format!(
"dependency_info.image_memory_barriers[{}].dst_stages",
barrier_index
)
.into(),
problem: "contains stages that are not supported by the queue family of the \
command buffer"
.into(),
vuids: &["VUID-vkCmdSetEvent2-dstStageMask-03828"],
..Default::default()
}));
}
}
Ok(())
}
#[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
pub unsafe fn set_event_unchecked(
&mut self,
event: &Event,
dependency_info: &DependencyInfo,
) -> &mut Self {
let &DependencyInfo {
mut dependency_flags,
@ -453,8 +817,193 @@ where
self
}
/// Calls `vkCmdWaitEvents` on the builder.
pub unsafe fn wait_events(&mut self, events: &[(Arc<Event>, DependencyInfo)]) -> &mut Self {
pub unsafe fn wait_events(
&mut self,
events: &[(Arc<Event>, DependencyInfo)],
) -> Result<&mut Self, Box<ValidationError>> {
self.validate_wait_events(events)?;
Ok(self.wait_events_unchecked(events))
}
fn validate_wait_events(
&self,
events: &[(Arc<Event>, DependencyInfo)],
) -> Result<(), Box<ValidationError>> {
let queue_family_properties = self.queue_family_properties();
if !queue_family_properties.queue_flags.intersects(
QueueFlags::GRAPHICS
| QueueFlags::COMPUTE
| QueueFlags::VIDEO_DECODE
| QueueFlags::VIDEO_ENCODE,
) {
return Err(Box::new(ValidationError {
problem: "the queue family of the command buffer does not support \
graphics, compute, video decode or video encode operations"
.into(),
vuids: &["VUID-vkCmdWaitEvents2-commandBuffer-cmdpool"],
..Default::default()
}));
}
for (event_index, (event, dependency_info)) in events.iter().enumerate() {
// VUID-vkCmdWaitEvents2-commandBuffer-cmdpool
assert_eq!(self.device(), event.device());
dependency_info
.validate(self.device())
.map_err(|err| err.add_context(format!("events[{}].1", event_index)))?;
let &DependencyInfo {
dependency_flags: _,
ref memory_barriers,
ref buffer_memory_barriers,
ref image_memory_barriers,
_ne,
} = dependency_info;
let supported_pipeline_stages =
PipelineStages::from(queue_family_properties.queue_flags);
for (barrier_index, memory_barrier) in memory_barriers.iter().enumerate() {
let &MemoryBarrier {
src_stages,
src_access: _,
dst_stages,
dst_access: _,
_ne: _,
} = memory_barrier;
if !supported_pipeline_stages.contains(src_stages) {
return Err(Box::new(ValidationError {
context: format!(
"events[{}].1.memory_barriers[{}].src_stages",
event_index, barrier_index
)
.into(),
problem: "contains stages that are not supported by the queue family of \
the command buffer"
.into(),
vuids: &["VUID-vkCmdSetEvent2-srcStageMask-03827"],
..Default::default()
}));
}
if !supported_pipeline_stages.contains(dst_stages) {
return Err(Box::new(ValidationError {
context: format!(
"events[{}].1.memory_barriers[{}].dst_stages",
event_index, barrier_index
)
.into(),
problem: "contains stages that are not supported by the queue family of \
the command buffer"
.into(),
vuids: &["VUID-vkCmdSetEvent2-dstStageMask-03828"],
..Default::default()
}));
}
}
for (barrier_index, buffer_memory_barrier) in buffer_memory_barriers.iter().enumerate()
{
let &BufferMemoryBarrier {
src_stages,
src_access: _,
dst_stages,
dst_access: _,
queue_family_ownership_transfer: _,
buffer: _,
range: _,
_ne: _,
} = buffer_memory_barrier;
if !supported_pipeline_stages.contains(src_stages) {
return Err(Box::new(ValidationError {
context: format!(
"events[{}].1.buffer_memory_barriers[{}].src_stages",
event_index, barrier_index
)
.into(),
problem: "contains stages that are not supported by the queue family of \
the command buffer"
.into(),
vuids: &["VUID-vkCmdSetEvent2-srcStageMask-03827"],
..Default::default()
}));
}
if !supported_pipeline_stages.contains(dst_stages) {
return Err(Box::new(ValidationError {
context: format!(
"events[{}].1.buffer_memory_barriers[{}].dst_stages",
event_index, barrier_index
)
.into(),
problem: "contains stages that are not supported by the queue family of \
the command buffer"
.into(),
vuids: &["VUID-vkCmdSetEvent2-dstStageMask-03828"],
..Default::default()
}));
}
}
for (barrier_index, image_memory_barrier) in image_memory_barriers.iter().enumerate() {
let &ImageMemoryBarrier {
src_stages,
src_access: _,
dst_stages,
dst_access: _,
old_layout: _,
new_layout: _,
queue_family_ownership_transfer: _,
image: _,
subresource_range: _,
_ne: _,
} = image_memory_barrier;
if !supported_pipeline_stages.contains(src_stages) {
return Err(Box::new(ValidationError {
context: format!(
"events[{}].1.image_memory_barriers[{}].src_stages",
event_index, barrier_index
)
.into(),
problem: "contains stages that are not supported by the queue family of \
the command buffer"
.into(),
vuids: &["VUID-vkCmdSetEvent2-srcStageMask-03827"],
..Default::default()
}));
}
if !supported_pipeline_stages.contains(dst_stages) {
return Err(Box::new(ValidationError {
context: format!(
"events[{}].1.image_memory_barriers[{}].dst_stages",
event_index, barrier_index
)
.into(),
problem: "contains stages that are not supported by the queue family of \
the command buffer"
.into(),
vuids: &["VUID-vkCmdSetEvent2-dstStageMask-03828"],
..Default::default()
}));
}
}
}
Ok(())
}
#[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
pub unsafe fn wait_events_unchecked(
&mut self,
events: &[(Arc<Event>, DependencyInfo)],
) -> &mut Self {
let fns = self.device().fns();
if self.device().enabled_features().synchronization2 {
@ -775,9 +1324,233 @@ where
self
}
/// Calls `vkCmdResetEvent` on the builder.
#[inline]
pub unsafe fn reset_event(&mut self, event: Arc<Event>, stages: PipelineStages) -> &mut Self {
pub unsafe fn reset_event(
&mut self,
event: &Event,
stages: PipelineStages,
) -> Result<&mut Self, Box<ValidationError>> {
self.validate_reset_event(event, stages)?;
Ok(self.reset_event_unchecked(event, stages))
}
fn validate_reset_event(
&self,
event: &Event,
stages: PipelineStages,
) -> Result<(), Box<ValidationError>> {
if !self.queue_family_properties().queue_flags.intersects(
QueueFlags::GRAPHICS
| QueueFlags::COMPUTE
| QueueFlags::VIDEO_DECODE
| QueueFlags::VIDEO_ENCODE,
) {
return Err(Box::new(ValidationError {
problem: "the queue family of the command buffer does not support \
graphics, compute, video decode or video encode operations"
.into(),
vuids: &["VUID-vkCmdResetEvent2-commandBuffer-cmdpool"],
..Default::default()
}));
}
let device = self.device();
// VUID-vkCmdResetEvent2-commonparent
assert_eq!(device, event.device());
stages
.validate_device(device)
.map_err(|err| ValidationError {
context: "stages".into(),
vuids: &["VUID-vkCmdResetEvent2-stageMask-parameter"],
..ValidationError::from_requirement(err)
})?;
if !device.enabled_features().synchronization2 {
if stages.contains_flags2() {
return Err(Box::new(ValidationError {
context: "stages".into(),
problem: "contains flags from `VkPipelineStageFlagBits2`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"synchronization2",
)])]),
..Default::default()
}));
}
}
if !device.enabled_features().geometry_shader {
if stages.intersects(PipelineStages::GEOMETRY_SHADER) {
return Err(Box::new(ValidationError {
context: "stages".into(),
problem: "contains `PipelineStages::GEOMETRY_SHADER`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"geometry_shader",
)])]),
vuids: &["VUID-vkCmdResetEvent2-stageMask-03929"],
}));
}
}
if !device.enabled_features().tessellation_shader {
if stages.intersects(
PipelineStages::TESSELLATION_CONTROL_SHADER
| PipelineStages::TESSELLATION_EVALUATION_SHADER,
) {
return Err(Box::new(ValidationError {
context: "stages".into(),
problem: "contains `PipelineStages::TESSELLATION_CONTROL_SHADER` or \
`PipelineStages::TESSELLATION_EVALUATION_SHADER`"
.into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"tessellation_shader",
)])]),
vuids: &["VUID-vkCmdResetEvent2-stageMask-03930"],
}));
}
}
if !device.enabled_features().conditional_rendering {
if stages.intersects(PipelineStages::CONDITIONAL_RENDERING) {
return Err(Box::new(ValidationError {
context: "stages".into(),
problem: "contains `PipelineStages::CONDITIONAL_RENDERING`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"conditional_rendering",
)])]),
vuids: &["VUID-vkCmdResetEvent2-stageMask-03931"],
}));
}
}
if !device.enabled_features().fragment_density_map {
if stages.intersects(PipelineStages::FRAGMENT_DENSITY_PROCESS) {
return Err(Box::new(ValidationError {
context: "stages".into(),
problem: "contains `PipelineStages::FRAGMENT_DENSITY_PROCESS`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"fragment_density_map",
)])]),
vuids: &["VUID-vkCmdResetEvent2-stageMask-03932"],
}));
}
}
if !device.enabled_features().transform_feedback {
if stages.intersects(PipelineStages::TRANSFORM_FEEDBACK) {
return Err(Box::new(ValidationError {
context: "stages".into(),
problem: "contains `PipelineStages::TRANSFORM_FEEDBACK`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"transform_feedback",
)])]),
vuids: &["VUID-vkCmdResetEvent2-stageMask-03933"],
}));
}
}
if !device.enabled_features().mesh_shader {
if stages.intersects(PipelineStages::MESH_SHADER) {
return Err(Box::new(ValidationError {
context: "stages".into(),
problem: "contains `PipelineStages::MESH_SHADER`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"mesh_shader",
)])]),
vuids: &["VUID-vkCmdResetEvent2-stageMask-03934"],
}));
}
}
if !device.enabled_features().task_shader {
if stages.intersects(PipelineStages::TASK_SHADER) {
return Err(Box::new(ValidationError {
context: "stages".into(),
problem: "contains `PipelineStages::TASK_SHADER`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"task_shader",
)])]),
vuids: &["VUID-vkCmdResetEvent2-stageMask-03935"],
}));
}
}
if !(device.enabled_features().attachment_fragment_shading_rate
|| device.enabled_features().shading_rate_image)
{
if stages.intersects(PipelineStages::FRAGMENT_SHADING_RATE_ATTACHMENT) {
return Err(Box::new(ValidationError {
context: "stages".into(),
problem: "contains `PipelineStages::FRAGMENT_SHADING_RATE_ATTACHMENT`".into(),
requires_one_of: RequiresOneOf(&[
RequiresAllOf(&[Requires::Feature("attachment_fragment_shading_rate")]),
RequiresAllOf(&[Requires::Feature("shading_rate_image")]),
]),
vuids: &["VUID-VkImageMemoryBarrier2-shadingRateImage-07316"],
}));
}
}
if !device.enabled_features().subpass_shading {
if stages.intersects(PipelineStages::SUBPASS_SHADING) {
return Err(Box::new(ValidationError {
context: "stages".into(),
problem: "contains `PipelineStages::SUBPASS_SHADING`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"subpass_shading",
)])]),
vuids: &["VUID-vkCmdResetEvent2-stageMask-04957"],
}));
}
}
if !device.enabled_features().invocation_mask {
if stages.intersects(PipelineStages::INVOCATION_MASK) {
return Err(Box::new(ValidationError {
context: "stages".into(),
problem: "contains `PipelineStages::INVOCATION_MASK`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"invocation_mask",
)])]),
vuids: &["VUID-vkCmdResetEvent2-stageMask-04995"],
}));
}
}
if !(device.enabled_extensions().nv_ray_tracing
|| device.enabled_features().ray_tracing_pipeline)
{
if stages.intersects(PipelineStages::RAY_TRACING_SHADER) {
return Err(Box::new(ValidationError {
context: "stages".into(),
problem: "contains `PipelineStages::RAY_TRACING_SHADER`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"ray_tracing_pipeline",
)])]),
vuids: &["VUID-vkCmdResetEvent2-stageMask-07946"],
}));
}
}
if stages.intersects(PipelineStages::HOST) {
return Err(Box::new(ValidationError {
context: "stages".into(),
problem: "contains `PipelineStages::HOST`".into(),
vuids: &["VUID-vkCmdResetEvent2-stageMask-03830"],
..Default::default()
}));
}
Ok(())
}
#[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
pub unsafe fn reset_event_unchecked(
&mut self,
event: &Event,
stages: PipelineStages,
) -> &mut Self {
let fns = self.device().fns();
if self.device().enabled_features().synchronization2 {

View File

@ -91,11 +91,11 @@
//! queue.queue_family_index(),
//! CommandBufferUsage::MultipleSubmit
//! ).unwrap()
//! .begin_render_pass(render_pass_begin_info, SubpassContents::Inline).unwrap()
//! .bind_pipeline_graphics(graphics_pipeline.clone())
//! .bind_vertex_buffers(0, vertex_buffer.clone())
//! .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().unwrap()
//! .end_render_pass(Default::default()).unwrap()
//! .build().unwrap();
//!
//! let _future = cb.execute(queue.clone());
@ -111,19 +111,8 @@
pub use self::{
auto::{AutoCommandBufferBuilder, PrimaryAutoCommandBuffer, SecondaryAutoCommandBuffer},
commands::{
clear::{ClearColorImageInfo, ClearDepthStencilImageInfo, ClearError},
copy::{
BlitImageInfo, BufferCopy, BufferImageCopy, CopyBufferInfo, CopyBufferInfoTyped,
CopyBufferToImageInfo, CopyError, CopyErrorResource, CopyImageInfo,
CopyImageToBufferInfo, ImageBlit, ImageCopy, ImageResolve, ResolveImageInfo,
},
pipeline::PipelineExecutionError,
query::QueryError,
render_pass::{
ClearAttachment, ClearRect, RenderPassBeginInfo, RenderPassError,
RenderingAttachmentInfo, RenderingAttachmentResolveInfo, RenderingInfo,
},
secondary::ExecuteCommandsError,
acceleration_structure::*, clear::*, copy::*, debug::*, dynamic_state::*, pipeline::*,
query::*, render_pass::*, secondary::*, sync::*,
},
traits::{
CommandBufferExecError, CommandBufferExecFuture, PrimaryCommandBufferAbstract,

View File

@ -22,7 +22,7 @@ use crate::{
},
PipelineStages,
},
DeviceSize, SafeDeref, VulkanObject,
DeviceSize, SafeDeref, ValidationError, VulkanObject,
};
use parking_lot::{Mutex, MutexGuard};
use std::{
@ -172,7 +172,7 @@ pub unsafe trait SecondaryCommandBufferAbstract:
/// and if so locks it.
///
/// If you call this function, then you should call `unlock` afterwards.
fn lock_record(&self) -> Result<(), CommandBufferExecError>;
fn lock_record(&self) -> Result<(), Box<ValidationError>>;
/// Unlocks the command buffer. Should be called once for each call to `lock_record`.
///
@ -198,7 +198,7 @@ where
(**self).inheritance_info()
}
fn lock_record(&self) -> Result<(), CommandBufferExecError> {
fn lock_record(&self) -> Result<(), Box<ValidationError>> {
(**self).lock_record()
}

View File

@ -94,11 +94,11 @@
//! method on a format.
use crate::{
device::physical::PhysicalDevice,
device::{physical::PhysicalDevice, Device},
image::{ImageAspects, ImageTiling},
macros::vulkan_bitflags,
shader::spirv::ImageFormat,
DeviceSize,
DeviceSize, Requires, RequiresAllOf, RequiresOneOf, ValidationError,
};
// Generated by build.rs
@ -276,9 +276,9 @@ impl ChromaSampling {
}
}
/// The numeric type that represents data of a format in memory.
/// The numeric format in memory of the components of a format.
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum NumericType {
pub enum NumericFormat {
/// Signed floating-point number.
SFLOAT,
/// Unsigned floating-point number.
@ -300,6 +300,38 @@ pub enum NumericType {
SRGB,
}
impl NumericFormat {
// https://registry.khronos.org/vulkan/specs/1.3-extensions/html/chap47.html#formats-numericformat
pub const fn numeric_type(self) -> NumericType {
match self {
NumericFormat::SFLOAT
| NumericFormat::UFLOAT
| NumericFormat::SNORM
| NumericFormat::UNORM
| NumericFormat::SSCALED
| NumericFormat::USCALED
| NumericFormat::SRGB => NumericType::Float,
NumericFormat::SINT => NumericType::Int,
NumericFormat::UINT => NumericType::Uint,
}
}
}
/// The numeric base type of a scalar value, in a format, a shader, or elsewhere.
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum NumericType {
Float,
Int,
Uint,
}
impl From<NumericFormat> for NumericType {
#[inline]
fn from(val: NumericFormat) -> Self {
val.numeric_type()
}
}
/// An opaque type that represents a format compatibility class.
///
/// Two formats are compatible if their compatibility classes compare equal.
@ -417,6 +449,40 @@ pub enum ClearValue {
DepthStencil((f32, u32)),
}
impl ClearValue {
pub(crate) fn validate(&self, device: &Device) -> Result<(), Box<ValidationError>> {
if let ClearValue::Depth(depth) | ClearValue::DepthStencil((depth, _)) = self {
if !(0.0..=1.0).contains(depth)
&& !device.enabled_extensions().ext_depth_range_unrestricted
{
return Err(Box::new(ValidationError {
problem: "is `ClearValue::Depth` or `ClearValue::DepthStencil`, and \
the depth value is not between 0.0 and 1.0 inclusive"
.into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::DeviceExtension(
"ext_depth_range_unrestricted",
)])]),
vuids: &["VUID-VkClearDepthStencilValue-depth-00022"],
..Default::default()
}));
}
}
Ok(())
}
pub(crate) fn clear_value_type(&self) -> ClearValueType {
match self {
ClearValue::Float(_) => ClearValueType::Float,
ClearValue::Int(_) => ClearValueType::Int,
ClearValue::Uint(_) => ClearValueType::Uint,
ClearValue::Depth(_) => ClearValueType::Depth,
ClearValue::Stencil(_) => ClearValueType::Stencil,
ClearValue::DepthStencil(_) => ClearValueType::DepthStencil,
}
}
}
impl From<ClearValue> for ash::vk::ClearValue {
#[inline]
fn from(val: ClearValue) -> Self {
@ -562,6 +628,16 @@ impl From<(f32, u32)> for ClearValue {
}
}
#[derive(Debug, PartialEq, Eq)]
pub(crate) enum ClearValueType {
Float,
Int,
Uint,
Depth,
Stencil,
DepthStencil,
}
/// A value that will be used to clear a color image.
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum ClearColorValue {
@ -573,6 +649,17 @@ pub enum ClearColorValue {
Uint([u32; 4]),
}
impl ClearColorValue {
/// Returns the numeric type of the clear value.
pub fn numeric_type(&self) -> NumericType {
match self {
ClearColorValue::Float(_) => NumericType::Float,
ClearColorValue::Int(_) => NumericType::Int,
ClearColorValue::Uint(_) => NumericType::Uint,
}
}
}
impl From<ClearColorValue> for ash::vk::ClearColorValue {
#[inline]
fn from(val: ClearColorValue) -> Self {

View File

@ -49,7 +49,7 @@ pub mod ycbcr;
use self::ycbcr::SamplerYcbcrConversion;
use crate::{
device::{Device, DeviceOwned, DeviceOwnedDebugWrapper},
format::FormatFeatures,
format::{FormatFeatures, NumericType},
image::{
view::{ImageView, ImageViewType},
ImageAspects,
@ -57,7 +57,6 @@ use crate::{
instance::InstanceOwnedDebugWrapper,
macros::{impl_id_counter, vulkan_enum},
pipeline::graphics::depth_stencil::CompareOp,
shader::ShaderScalarType,
Requires, RequiresAllOf, RequiresOneOf, Validated, ValidationError, VulkanError, VulkanObject,
};
use std::{mem::MaybeUninit, num::NonZeroU64, ops::RangeInclusive, ptr, sync::Arc};
@ -395,18 +394,18 @@ impl Sampler {
if let Some(border_color) = self.border_color {
let aspects = image_view.subresource_range().aspects;
let view_scalar_type = ShaderScalarType::from(
let view_numeric_type = NumericType::from(
if aspects.intersects(
ImageAspects::COLOR
| ImageAspects::PLANE_0
| ImageAspects::PLANE_1
| ImageAspects::PLANE_2,
) {
image_view.format().type_color().unwrap()
image_view.format().numeric_format_color().unwrap()
} else if aspects.intersects(ImageAspects::DEPTH) {
image_view.format().type_depth().unwrap()
image_view.format().numeric_format_depth().unwrap()
} else if aspects.intersects(ImageAspects::STENCIL) {
image_view.format().type_stencil().unwrap()
image_view.format().numeric_format_stencil().unwrap()
} else {
// Per `ImageViewBuilder::aspects` and
// VUID-VkDescriptorImageInfo-imageView-01976
@ -421,10 +420,7 @@ impl Sampler {
// The sampler borderColor is an integer type and the image view
// format is not one of the VkFormat integer types or a stencil
// component of a depth/stencil format.
if !matches!(
view_scalar_type,
ShaderScalarType::Sint | ShaderScalarType::Uint
) {
if !matches!(view_numeric_type, NumericType::Int | NumericType::Uint) {
return Err(Box::new(ValidationError {
problem: "the sampler has an integer border color, and \
the image view does not have an integer format"
@ -439,7 +435,7 @@ impl Sampler {
// The sampler borderColor is a float type and the image view
// format is not one of the VkFormat float types or a depth
// component of a depth/stencil format.
if !matches!(view_scalar_type, ShaderScalarType::Float) {
if !matches!(view_numeric_type, NumericType::Float) {
return Err(Box::new(ValidationError {
problem: "the sampler has an floating-point border color, and \
the image view does not have a floating-point format"

View File

@ -111,7 +111,7 @@
use crate::{
device::{Device, DeviceOwned},
format::{ChromaSampling, Format, FormatFeatures, NumericType},
format::{ChromaSampling, Format, FormatFeatures, NumericFormat},
image::sampler::{ComponentMapping, ComponentSwizzle, Filter},
instance::InstanceOwnedDebugWrapper,
macros::{impl_id_counter, vulkan_enum},
@ -518,8 +518,8 @@ impl SamplerYcbcrConversionCreateInfo {
})?;
if !format
.type_color()
.map_or(false, |ty| ty == NumericType::UNORM)
.numeric_format_color()
.map_or(false, |ty| ty == NumericFormat::UNORM)
{
return Err(Box::new(ValidationError {
context: "format".into(),

View File

@ -1170,7 +1170,7 @@ unsafe fn get_format_features(view_format: Format, image: &Image) -> FormatFeatu
|| device.enabled_extensions().khr_format_feature_flags2)
&& matches!(image.tiling(), ImageTiling::Linear | ImageTiling::Optimal)
{
if view_format.type_color().is_none()
if view_format.numeric_format_color().is_none()
&& format_features.intersects(FormatFeatures::SAMPLED_IMAGE)
{
format_features |= FormatFeatures::SAMPLED_IMAGE_DEPTH_COMPARISON;

View File

@ -493,12 +493,14 @@ mod tests {
)
.unwrap();
cbb.bind_pipeline_compute(pipeline.clone())
.unwrap()
.bind_descriptor_sets(
PipelineBindPoint::Compute,
pipeline.layout().clone(),
0,
set,
)
.unwrap()
.dispatch([1, 1, 1])
.unwrap();
let cb = cbb.build().unwrap();

View File

@ -74,7 +74,7 @@ use super::{
};
use crate::{
device::{Device, DeviceOwned, DeviceOwnedDebugWrapper},
format::{FormatFeatures, NumericType},
format::FormatFeatures,
image::{ImageAspect, ImageAspects},
instance::InstanceOwnedDebugWrapper,
macros::impl_id_counter,
@ -91,7 +91,7 @@ use crate::{
},
shader::{
DescriptorBindingRequirements, FragmentShaderExecution, FragmentTestsStages,
ShaderExecution, ShaderScalarType, ShaderStage, ShaderStages,
ShaderExecution, ShaderStage, ShaderStages,
},
Requires, RequiresAllOf, RequiresOneOf, Validated, ValidationError, VulkanError, VulkanObject,
};
@ -2702,27 +2702,18 @@ impl GraphicsPipelineCreateInfo {
// same location but in different components.
let shader_type = element.ty.base_type;
let attribute_type = attribute_desc.format.type_color().unwrap();
let attribute_type = attribute_desc
.format
.numeric_format_color()
.unwrap()
.numeric_type();
// VUID?
if !matches!(
(shader_type, attribute_type),
(
ShaderScalarType::Float,
NumericType::SFLOAT
| NumericType::UFLOAT
| NumericType::SNORM
| NumericType::UNORM
| NumericType::SSCALED
| NumericType::USCALED
| NumericType::SRGB,
) | (ShaderScalarType::Sint, NumericType::SINT)
| (ShaderScalarType::Uint, NumericType::UINT)
) {
if shader_type != attribute_type {
return Err(Box::new(ValidationError {
problem: format!(
"`vertex_input_state.attributes[{}].format` has a different \
scalar type than the vertex shader input variable with \
numeric type than the vertex shader input variable with \
location {0}",
location,
)

View File

@ -496,8 +496,8 @@ impl FramebufferCreateInfo {
for image_view in attachments.iter() {
let image_view_extent = image_view.image().extent();
let image_view_array_layers = image_view.subresource_range().array_layers.end
- image_view.subresource_range().array_layers.start;
let image_view_array_layers =
image_view.subresource_range().array_layers.len() as u32;
auto_extent[0] = auto_extent[0].min(image_view_extent[0]);
auto_extent[1] = auto_extent[1].min(image_view_extent[1]);

View File

@ -28,7 +28,7 @@
pub use self::framebuffer::{Framebuffer, FramebufferCreateFlags, FramebufferCreateInfo};
use crate::{
device::{Device, DeviceOwned, QueueFlags},
format::{Format, FormatFeatures},
format::{ClearValueType, Format, FormatFeatures, NumericType},
image::{ImageAspects, ImageLayout, SampleCount},
instance::InstanceOwnedDebugWrapper,
macros::{impl_id_counter, vulkan_bitflags, vulkan_bitflags_enum, vulkan_enum},
@ -1261,7 +1261,7 @@ impl RenderPassCreateInfo {
let resolve_format = resolve_attachment_desc.format;
if !(resolve_format.components()[0] == format.components()[0]
&& resolve_format.type_depth() == format.type_depth())
&& resolve_format.numeric_format_depth() == format.numeric_format_depth())
{
return Err(Box::new(ValidationError {
problem: format!(
@ -1282,7 +1282,8 @@ impl RenderPassCreateInfo {
}
if !(resolve_format.components()[1] == format.components()[1]
&& resolve_format.type_stencil() == format.type_stencil())
&& resolve_format.numeric_format_stencil()
== format.numeric_format_stencil())
{
return Err(Box::new(ValidationError {
problem: format!(
@ -2187,6 +2188,29 @@ impl AttachmentDescription {
Ok(())
}
pub(crate) fn required_clear_value(&self) -> Option<ClearValueType> {
if let Some(numeric_format) = self.format.numeric_format_color() {
(self.load_op == AttachmentLoadOp::Clear).then(|| match numeric_format.numeric_type() {
NumericType::Float => ClearValueType::Float,
NumericType::Int => ClearValueType::Int,
NumericType::Uint => ClearValueType::Uint,
})
} else {
let aspects = self.format.aspects();
let need_depth =
aspects.intersects(ImageAspects::DEPTH) && self.load_op == AttachmentLoadOp::Clear;
let need_stencil = aspects.intersects(ImageAspects::STENCIL)
&& self.stencil_load_op.unwrap_or(self.load_op) == AttachmentLoadOp::Clear;
match (need_depth, need_stencil) {
(true, true) => Some(ClearValueType::DepthStencil),
(true, false) => Some(ClearValueType::Depth),
(false, true) => Some(ClearValueType::Stencil),
(false, false) => None,
}
}
}
}
vulkan_bitflags! {

View File

@ -730,7 +730,7 @@ pub struct DescriptorBindingRequirements {
/// The base scalar type required for the format of image views bound to this binding.
/// This is `None` for non-image bindings.
pub image_scalar_type: Option<ShaderScalarType>,
pub image_scalar_type: Option<NumericType>,
/// The view type that is required for image views bound to this binding.
/// This is `None` for non-image bindings.
@ -1140,7 +1140,7 @@ pub struct ShaderInterfaceEntry {
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct ShaderInterfaceEntryType {
/// The base numeric type.
pub base_type: ShaderScalarType,
pub base_type: NumericType,
/// The number of vector components. Must be in the range 1..=4.
pub num_components: u32,
@ -1160,32 +1160,6 @@ impl ShaderInterfaceEntryType {
}
}
/// The numeric base type of a shader variable.
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum ShaderScalarType {
Float,
Sint,
Uint,
}
// https://registry.khronos.org/vulkan/specs/1.3-extensions/html/chap43.html#formats-numericformat
impl From<NumericType> for ShaderScalarType {
#[inline]
fn from(val: NumericType) -> Self {
match val {
NumericType::SFLOAT => Self::Float,
NumericType::UFLOAT => Self::Float,
NumericType::SINT => Self::Sint,
NumericType::UINT => Self::Uint,
NumericType::SNORM => Self::Float,
NumericType::UNORM => Self::Float,
NumericType::SSCALED => Self::Float,
NumericType::USCALED => Self::Float,
NumericType::SRGB => Self::Float,
}
}
}
vulkan_bitflags_enum! {
#[non_exhaustive]

View File

@ -20,8 +20,8 @@ use crate::{
StorageClass,
},
DescriptorIdentifier, DescriptorRequirements, EntryPointInfo, GeometryShaderExecution,
GeometryShaderInput, ShaderExecution, ShaderInterface, ShaderInterfaceEntry,
ShaderInterfaceEntryType, ShaderScalarType, ShaderStage, SpecializationConstant,
GeometryShaderInput, NumericType, ShaderExecution, ShaderInterface, ShaderInterfaceEntry,
ShaderInterfaceEntryType, ShaderStage, SpecializationConstant,
},
DeviceSize,
};
@ -854,14 +854,14 @@ fn descriptor_binding_requirements_of(spirv: &Spirv, variable_id: Id) -> Descrip
} => {
assert!(width == 32); // TODO: 64-bit components
match signedness {
0 => ShaderScalarType::Uint,
1 => ShaderScalarType::Sint,
0 => NumericType::Uint,
1 => NumericType::Int,
_ => unreachable!(),
}
}
Instruction::TypeFloat { width, .. } => {
assert!(width == 32); // TODO: 64-bit components
ShaderScalarType::Float
NumericType::Float
}
_ => unreachable!(),
});
@ -1347,8 +1347,8 @@ fn shader_interface_type_of(
assert!(!ignore_first_array);
ShaderInterfaceEntryType {
base_type: match signedness {
0 => ShaderScalarType::Uint,
1 => ShaderScalarType::Sint,
0 => NumericType::Uint,
1 => NumericType::Int,
_ => unreachable!(),
},
num_components: 1,
@ -1363,7 +1363,7 @@ fn shader_interface_type_of(
Instruction::TypeFloat { width, .. } => {
assert!(!ignore_first_array);
ShaderInterfaceEntryType {
base_type: ShaderScalarType::Float,
base_type: NumericType::Float,
num_components: 1,
num_elements: 1,
is_64bit: match width {

File diff suppressed because it is too large Load Diff