mirror of
https://github.com/vulkano-rs/vulkano.git
synced 2024-11-25 16:25:31 +00:00
Improve render pass commands, more validation (#1884)
* Use only the selected range of buffer and image views in synchronization * Improve render pass commands, more validation Co-authored-by: Austin Johnson <me@austinj.work>
This commit is contained in:
parent
1c71883cd4
commit
9e2b41a5c4
@ -26,7 +26,9 @@ use std::{
|
||||
};
|
||||
use vulkano::{
|
||||
buffer::CpuBufferPool,
|
||||
command_buffer::{AutoCommandBufferBuilder, CommandBufferUsage, SubpassContents},
|
||||
command_buffer::{
|
||||
AutoCommandBufferBuilder, CommandBufferUsage, RenderPassBeginInfo, SubpassContents,
|
||||
},
|
||||
device::{
|
||||
physical::{PhysicalDevice, PhysicalDeviceType},
|
||||
Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo,
|
||||
@ -268,8 +270,6 @@ fn main() {
|
||||
recreate_swapchain = true;
|
||||
}
|
||||
|
||||
let clear_values = vec![[0.0, 0.0, 1.0, 1.0].into()];
|
||||
|
||||
// Rotate once (PI*2) every 5 seconds
|
||||
let elapsed = SystemTime::now()
|
||||
.duration_since(UNIX_EPOCH)
|
||||
@ -312,9 +312,11 @@ fn main() {
|
||||
.unwrap();
|
||||
builder
|
||||
.begin_render_pass(
|
||||
framebuffers[image_num].clone(),
|
||||
RenderPassBeginInfo {
|
||||
clear_values: vec![Some([0.0, 0.0, 1.0, 1.0].into())],
|
||||
..RenderPassBeginInfo::framebuffer(framebuffers[image_num].clone())
|
||||
},
|
||||
SubpassContents::Inline,
|
||||
clear_values,
|
||||
)
|
||||
.unwrap()
|
||||
.set_viewport(0, [viewport.clone()])
|
||||
|
@ -9,17 +9,15 @@
|
||||
|
||||
use std::sync::Arc;
|
||||
use vulkano::{
|
||||
command_buffer::{AutoCommandBufferBuilder, CommandBufferUsage, SubpassContents},
|
||||
command_buffer::{
|
||||
AutoCommandBufferBuilder, ClearAttachment, ClearRect, CommandBufferUsage,
|
||||
RenderPassBeginInfo, SubpassContents,
|
||||
},
|
||||
device::{
|
||||
physical::{PhysicalDevice, PhysicalDeviceType},
|
||||
Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo,
|
||||
},
|
||||
format::ClearValue,
|
||||
image::{
|
||||
attachment::{ClearAttachment, ClearRect},
|
||||
view::ImageView,
|
||||
ImageUsage, SwapchainImage,
|
||||
},
|
||||
image::{view::ImageView, ImageUsage, SwapchainImage},
|
||||
instance::{Instance, InstanceCreateInfo},
|
||||
pipeline::{graphics::viewport::ViewportState, GraphicsPipeline},
|
||||
render_pass::{Framebuffer, FramebufferCreateInfo, RenderPass, Subpass},
|
||||
@ -230,7 +228,6 @@ fn main() {
|
||||
recreate_swapchain = true;
|
||||
}
|
||||
|
||||
let clear_values = vec![[0.0, 0.0, 1.0, 1.0].into()];
|
||||
let mut builder = AutoCommandBufferBuilder::primary(
|
||||
device.clone(),
|
||||
queue.family(),
|
||||
@ -239,9 +236,11 @@ fn main() {
|
||||
.unwrap();
|
||||
builder
|
||||
.begin_render_pass(
|
||||
framebuffers[image_num].clone(),
|
||||
RenderPassBeginInfo {
|
||||
clear_values: vec![Some([0.0, 0.0, 1.0, 1.0].into())],
|
||||
..RenderPassBeginInfo::framebuffer(framebuffers[image_num].clone())
|
||||
},
|
||||
SubpassContents::Inline,
|
||||
clear_values,
|
||||
)
|
||||
.unwrap()
|
||||
.bind_pipeline_graphics(pipeline.clone())
|
||||
@ -249,32 +248,29 @@ fn main() {
|
||||
// Note that the ClearRect offsets and extents are not affected by the viewport,
|
||||
// they are directly applied to the rendering image
|
||||
.clear_attachments(
|
||||
[ClearAttachment::Color(
|
||||
ClearValue::Float([1.0, 0.0, 0.0, 1.0]),
|
||||
0,
|
||||
)],
|
||||
[ClearAttachment::Color {
|
||||
color_attachment: 0,
|
||||
clear_value: [1.0, 0.0, 0.0, 1.0].into(),
|
||||
}],
|
||||
[
|
||||
// Fixed offset and extent
|
||||
ClearRect {
|
||||
rect_offset: [0, 0],
|
||||
rect_extent: [100, 100],
|
||||
base_array_layer: 0,
|
||||
layer_count: 1,
|
||||
offset: [0, 0],
|
||||
extent: [100, 100],
|
||||
array_layers: 0..1,
|
||||
},
|
||||
// Fixed offset
|
||||
// Relative extent
|
||||
ClearRect {
|
||||
rect_offset: [100, 150],
|
||||
rect_extent: [width / 4, height / 4],
|
||||
base_array_layer: 0,
|
||||
layer_count: 1,
|
||||
offset: [100, 150],
|
||||
extent: [width / 4, height / 4],
|
||||
array_layers: 0..1,
|
||||
},
|
||||
// Relative offset and extent
|
||||
ClearRect {
|
||||
rect_offset: [width / 2, height / 2],
|
||||
rect_extent: [width / 3, height / 5],
|
||||
base_array_layer: 0,
|
||||
layer_count: 1,
|
||||
offset: [width / 2, height / 2],
|
||||
extent: [width / 3, height / 5],
|
||||
array_layers: 0..1,
|
||||
},
|
||||
],
|
||||
)
|
||||
|
@ -17,7 +17,7 @@ use std::sync::Arc;
|
||||
use vulkano::{
|
||||
command_buffer::{
|
||||
AutoCommandBufferBuilder, CommandBufferUsage, PrimaryAutoCommandBuffer,
|
||||
SecondaryCommandBuffer, SubpassContents,
|
||||
RenderPassBeginInfo, SecondaryCommandBuffer, SubpassContents,
|
||||
},
|
||||
device::Queue,
|
||||
format::Format,
|
||||
@ -300,14 +300,16 @@ impl FrameSystem {
|
||||
.unwrap();
|
||||
command_buffer_builder
|
||||
.begin_render_pass(
|
||||
framebuffer.clone(),
|
||||
RenderPassBeginInfo {
|
||||
clear_values: vec![
|
||||
Some([0.0, 0.0, 0.0, 0.0].into()),
|
||||
Some([0.0, 0.0, 0.0, 0.0].into()),
|
||||
Some([0.0, 0.0, 0.0, 0.0].into()),
|
||||
Some(1.0f32.into()),
|
||||
],
|
||||
..RenderPassBeginInfo::framebuffer(framebuffer.clone())
|
||||
},
|
||||
SubpassContents::SecondaryCommandBuffers,
|
||||
vec![
|
||||
[0.0, 0.0, 0.0, 0.0].into(),
|
||||
[0.0, 0.0, 0.0, 0.0].into(),
|
||||
[0.0, 0.0, 0.0, 0.0].into(),
|
||||
1.0f32.into(),
|
||||
],
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
|
@ -16,7 +16,7 @@ mod linux {
|
||||
buffer::{BufferUsage, CpuAccessibleBuffer, TypedBufferAccess},
|
||||
command_buffer::{
|
||||
submit::SubmitCommandBufferBuilder, AutoCommandBufferBuilder, CommandBufferUsage,
|
||||
SubpassContents,
|
||||
RenderPassBeginInfo, SubpassContents,
|
||||
},
|
||||
descriptor_set::{PersistentDescriptorSet, WriteDescriptorSet},
|
||||
device::{
|
||||
@ -296,7 +296,6 @@ mod linux {
|
||||
recreate_swapchain = true;
|
||||
}
|
||||
|
||||
let clear_values = vec![[0.0, 0.0, 1.0, 1.0].into()];
|
||||
let mut builder = AutoCommandBufferBuilder::primary(
|
||||
device.clone(),
|
||||
queue.family(),
|
||||
@ -305,9 +304,11 @@ mod linux {
|
||||
.unwrap();
|
||||
builder
|
||||
.begin_render_pass(
|
||||
framebuffers[image_num].clone(),
|
||||
RenderPassBeginInfo {
|
||||
clear_values: vec![Some([0.0, 0.0, 1.0, 1.0].into())],
|
||||
..RenderPassBeginInfo::framebuffer(framebuffers[image_num].clone())
|
||||
},
|
||||
SubpassContents::Inline,
|
||||
clear_values,
|
||||
)
|
||||
.unwrap()
|
||||
.set_viewport(0, [viewport.clone()])
|
||||
|
@ -14,7 +14,7 @@ use vulkano::{
|
||||
command_buffer::{
|
||||
AutoCommandBufferBuilder, BlitImageInfo, BufferImageCopy, ClearColorImageInfo,
|
||||
CommandBufferUsage, CopyBufferToImageInfo, CopyImageInfo, ImageBlit, ImageCopy,
|
||||
PrimaryCommandBuffer, SubpassContents,
|
||||
PrimaryCommandBuffer, RenderPassBeginInfo, SubpassContents,
|
||||
},
|
||||
descriptor_set::{PersistentDescriptorSet, WriteDescriptorSet},
|
||||
device::{
|
||||
@ -378,7 +378,6 @@ fn main() {
|
||||
recreate_swapchain = true;
|
||||
}
|
||||
|
||||
let clear_values = vec![[0.0, 0.0, 1.0, 1.0].into()];
|
||||
let mut builder = AutoCommandBufferBuilder::primary(
|
||||
device.clone(),
|
||||
queue.family(),
|
||||
@ -387,9 +386,11 @@ fn main() {
|
||||
.unwrap();
|
||||
builder
|
||||
.begin_render_pass(
|
||||
framebuffers[image_num].clone(),
|
||||
RenderPassBeginInfo {
|
||||
clear_values: vec![Some([0.0, 0.0, 1.0, 1.0].into())],
|
||||
..RenderPassBeginInfo::framebuffer(framebuffers[image_num].clone())
|
||||
},
|
||||
SubpassContents::Inline,
|
||||
clear_values,
|
||||
)
|
||||
.unwrap()
|
||||
.set_viewport(0, [viewport.clone()])
|
||||
|
@ -11,7 +11,9 @@ use bytemuck::{Pod, Zeroable};
|
||||
use std::{io::Cursor, sync::Arc};
|
||||
use vulkano::{
|
||||
buffer::{BufferUsage, CpuAccessibleBuffer, TypedBufferAccess},
|
||||
command_buffer::{AutoCommandBufferBuilder, CommandBufferUsage, SubpassContents},
|
||||
command_buffer::{
|
||||
AutoCommandBufferBuilder, CommandBufferUsage, RenderPassBeginInfo, SubpassContents,
|
||||
},
|
||||
descriptor_set::{PersistentDescriptorSet, WriteDescriptorSet},
|
||||
device::{
|
||||
physical::{PhysicalDevice, PhysicalDeviceType},
|
||||
@ -296,7 +298,6 @@ fn main() {
|
||||
recreate_swapchain = true;
|
||||
}
|
||||
|
||||
let clear_values = vec![[0.0, 0.0, 1.0, 1.0].into()];
|
||||
let mut builder = AutoCommandBufferBuilder::primary(
|
||||
device.clone(),
|
||||
queue.family(),
|
||||
@ -305,9 +306,11 @@ fn main() {
|
||||
.unwrap();
|
||||
builder
|
||||
.begin_render_pass(
|
||||
framebuffers[image_num].clone(),
|
||||
RenderPassBeginInfo {
|
||||
clear_values: vec![Some([0.0, 0.0, 1.0, 1.0].into())],
|
||||
..RenderPassBeginInfo::framebuffer(framebuffers[image_num].clone())
|
||||
},
|
||||
SubpassContents::Inline,
|
||||
clear_values,
|
||||
)
|
||||
.unwrap()
|
||||
.set_viewport(0, [viewport.clone()])
|
||||
|
@ -20,7 +20,9 @@ use bytemuck::{Pod, Zeroable};
|
||||
use std::{io::Cursor, sync::Arc};
|
||||
use vulkano::{
|
||||
buffer::{BufferUsage, CpuAccessibleBuffer, TypedBufferAccess},
|
||||
command_buffer::{AutoCommandBufferBuilder, CommandBufferUsage, SubpassContents},
|
||||
command_buffer::{
|
||||
AutoCommandBufferBuilder, CommandBufferUsage, RenderPassBeginInfo, SubpassContents,
|
||||
},
|
||||
descriptor_set::{PersistentDescriptorSet, WriteDescriptorSet},
|
||||
device::{
|
||||
physical::{PhysicalDevice, PhysicalDeviceType},
|
||||
@ -305,7 +307,6 @@ fn main() {
|
||||
recreate_swapchain = true;
|
||||
}
|
||||
|
||||
let clear_values = vec![[0.0, 0.0, 1.0, 1.0].into()];
|
||||
let mut builder = AutoCommandBufferBuilder::primary(
|
||||
device.clone(),
|
||||
queue.family(),
|
||||
@ -314,9 +315,11 @@ fn main() {
|
||||
.unwrap();
|
||||
builder
|
||||
.begin_render_pass(
|
||||
framebuffers[image_num].clone(),
|
||||
RenderPassBeginInfo {
|
||||
clear_values: vec![Some([0.0, 0.0, 1.0, 1.0].into())],
|
||||
..RenderPassBeginInfo::framebuffer(framebuffers[image_num].clone())
|
||||
},
|
||||
SubpassContents::Inline,
|
||||
clear_values,
|
||||
)
|
||||
.unwrap()
|
||||
.set_viewport(0, [viewport.clone()])
|
||||
|
@ -29,7 +29,8 @@ use std::sync::Arc;
|
||||
use vulkano::{
|
||||
buffer::{BufferUsage, CpuBufferPool},
|
||||
command_buffer::{
|
||||
AutoCommandBufferBuilder, CommandBufferUsage, DrawIndirectCommand, SubpassContents,
|
||||
AutoCommandBufferBuilder, CommandBufferUsage, DrawIndirectCommand, RenderPassBeginInfo,
|
||||
SubpassContents,
|
||||
},
|
||||
descriptor_set::{PersistentDescriptorSet, WriteDescriptorSet},
|
||||
device::{
|
||||
@ -332,8 +333,6 @@ fn main() {
|
||||
recreate_swapchain = true;
|
||||
}
|
||||
|
||||
let clear_values = vec![[0.0, 0.0, 1.0, 1.0].into()];
|
||||
|
||||
// Allocate a GPU buffer to hold the arguments for this frames draw call. The compute
|
||||
// shader will only update vertex_count, so set the other parameters correctly here.
|
||||
let indirect_commands = [DrawIndirectCommand {
|
||||
@ -381,9 +380,11 @@ fn main() {
|
||||
.dispatch([1, 1, 1])
|
||||
.unwrap()
|
||||
.begin_render_pass(
|
||||
framebuffers[image_num].clone(),
|
||||
RenderPassBeginInfo {
|
||||
clear_values: vec![Some([0.0, 0.0, 1.0, 1.0].into())],
|
||||
..RenderPassBeginInfo::framebuffer(framebuffers[image_num].clone())
|
||||
},
|
||||
SubpassContents::Inline,
|
||||
clear_values,
|
||||
)
|
||||
.unwrap()
|
||||
// The indirect draw call is placed in the command buffer with a reference to the GPU buffer that will
|
||||
|
@ -16,7 +16,9 @@ use bytemuck::{Pod, Zeroable};
|
||||
use std::sync::Arc;
|
||||
use vulkano::{
|
||||
buffer::{BufferUsage, CpuAccessibleBuffer, TypedBufferAccess},
|
||||
command_buffer::{AutoCommandBufferBuilder, CommandBufferUsage, SubpassContents},
|
||||
command_buffer::{
|
||||
AutoCommandBufferBuilder, CommandBufferUsage, RenderPassBeginInfo, SubpassContents,
|
||||
},
|
||||
device::{
|
||||
physical::{PhysicalDevice, PhysicalDeviceType},
|
||||
Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo,
|
||||
@ -327,8 +329,6 @@ fn main() {
|
||||
recreate_swapchain = true;
|
||||
}
|
||||
|
||||
let clear_values = vec![[0.0, 0.0, 1.0, 1.0].into()];
|
||||
|
||||
let mut builder = AutoCommandBufferBuilder::primary(
|
||||
device.clone(),
|
||||
queue.family(),
|
||||
@ -337,9 +337,11 @@ fn main() {
|
||||
.unwrap();
|
||||
builder
|
||||
.begin_render_pass(
|
||||
framebuffers[image_num].clone(),
|
||||
RenderPassBeginInfo {
|
||||
clear_values: vec![Some([0.0, 0.0, 1.0, 1.0].into())],
|
||||
..RenderPassBeginInfo::framebuffer(framebuffers[image_num].clone())
|
||||
},
|
||||
SubpassContents::Inline,
|
||||
clear_values,
|
||||
)
|
||||
.unwrap()
|
||||
.set_viewport(0, [viewport.clone()])
|
||||
|
@ -13,7 +13,9 @@ use crate::{
|
||||
};
|
||||
use std::sync::Arc;
|
||||
use vulkano::{
|
||||
command_buffer::{AutoCommandBufferBuilder, CommandBufferUsage, SubpassContents},
|
||||
command_buffer::{
|
||||
AutoCommandBufferBuilder, CommandBufferUsage, RenderPassBeginInfo, SubpassContents,
|
||||
},
|
||||
device::Queue,
|
||||
format::Format,
|
||||
image::ImageAccess,
|
||||
@ -86,9 +88,11 @@ impl RenderPassPlaceOverFrame {
|
||||
// Begin render pass
|
||||
command_buffer_builder
|
||||
.begin_render_pass(
|
||||
framebuffer,
|
||||
RenderPassBeginInfo {
|
||||
clear_values: vec![Some([0.0; 4].into())],
|
||||
..RenderPassBeginInfo::framebuffer(framebuffer)
|
||||
},
|
||||
SubpassContents::SecondaryCommandBuffers,
|
||||
vec![[0.0; 4].into()],
|
||||
)
|
||||
.unwrap();
|
||||
// Create secondary command buffer from texture pipeline & send draw commands
|
||||
|
@ -70,13 +70,13 @@ use vulkano::{
|
||||
buffer::{BufferUsage, CpuAccessibleBuffer, TypedBufferAccess},
|
||||
command_buffer::{
|
||||
AutoCommandBufferBuilder, CommandBufferUsage, CopyImageToBufferInfo, PrimaryCommandBuffer,
|
||||
SubpassContents,
|
||||
RenderPassBeginInfo, SubpassContents,
|
||||
},
|
||||
device::{
|
||||
physical::{PhysicalDevice, PhysicalDeviceType},
|
||||
Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo,
|
||||
},
|
||||
format::{ClearValue, Format},
|
||||
format::Format,
|
||||
image::{view::ImageView, AttachmentImage, ImageDimensions, SampleCount, StorageImage},
|
||||
impl_vertex,
|
||||
instance::{Instance, InstanceCreateInfo},
|
||||
@ -306,9 +306,11 @@ fn main() {
|
||||
.unwrap();
|
||||
builder
|
||||
.begin_render_pass(
|
||||
framebuffer.clone(),
|
||||
RenderPassBeginInfo {
|
||||
clear_values: vec![Some([0.0, 0.0, 1.0, 1.0].into()), None],
|
||||
..RenderPassBeginInfo::framebuffer(framebuffer.clone())
|
||||
},
|
||||
SubpassContents::Inline,
|
||||
vec![[0.0, 0.0, 1.0, 1.0].into(), ClearValue::None],
|
||||
)
|
||||
.unwrap()
|
||||
.set_viewport(0, [viewport.clone()])
|
||||
|
@ -20,7 +20,9 @@ use bytemuck::{Pod, Zeroable};
|
||||
use std::{collections::HashMap, sync::Arc};
|
||||
use vulkano::{
|
||||
buffer::{BufferUsage, CpuAccessibleBuffer, TypedBufferAccess},
|
||||
command_buffer::{AutoCommandBufferBuilder, CommandBufferUsage, SubpassContents},
|
||||
command_buffer::{
|
||||
AutoCommandBufferBuilder, CommandBufferUsage, RenderPassBeginInfo, SubpassContents,
|
||||
},
|
||||
device::{
|
||||
physical::{PhysicalDevice, PhysicalDeviceType},
|
||||
Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo,
|
||||
@ -382,8 +384,6 @@ fn main() {
|
||||
*recreate_swapchain = true;
|
||||
}
|
||||
|
||||
let clear_values = vec![[0.0, 0.0, 1.0, 1.0].into()];
|
||||
|
||||
let mut builder = AutoCommandBufferBuilder::primary(
|
||||
device.clone(),
|
||||
queue.family(),
|
||||
@ -393,9 +393,11 @@ fn main() {
|
||||
|
||||
builder
|
||||
.begin_render_pass(
|
||||
framebuffers[image_num].clone(),
|
||||
RenderPassBeginInfo {
|
||||
clear_values: vec![Some([0.0, 0.0, 1.0, 1.0].into())],
|
||||
..RenderPassBeginInfo::framebuffer(framebuffers[image_num].clone())
|
||||
},
|
||||
SubpassContents::Inline,
|
||||
clear_values,
|
||||
)
|
||||
.unwrap()
|
||||
.set_viewport(0, [viewport.clone()])
|
||||
|
@ -13,7 +13,9 @@ use crate::{
|
||||
};
|
||||
use std::sync::Arc;
|
||||
use vulkano::{
|
||||
command_buffer::{AutoCommandBufferBuilder, CommandBufferUsage, SubpassContents},
|
||||
command_buffer::{
|
||||
AutoCommandBufferBuilder, CommandBufferUsage, RenderPassBeginInfo, SubpassContents,
|
||||
},
|
||||
device::Queue,
|
||||
format::Format,
|
||||
image::ImageAccess,
|
||||
@ -86,9 +88,11 @@ impl RenderPassPlaceOverFrame {
|
||||
// Begin render pass
|
||||
command_buffer_builder
|
||||
.begin_render_pass(
|
||||
framebuffer,
|
||||
RenderPassBeginInfo {
|
||||
clear_values: vec![Some([0.0; 4].into())],
|
||||
..RenderPassBeginInfo::framebuffer(framebuffer)
|
||||
},
|
||||
SubpassContents::SecondaryCommandBuffers,
|
||||
vec![[0.0; 4].into()],
|
||||
)
|
||||
.unwrap();
|
||||
// Create secondary command buffer from texture pipeline & send draw commands
|
||||
|
@ -19,7 +19,7 @@ use vulkano::{
|
||||
buffer::{BufferUsage, CpuAccessibleBuffer, TypedBufferAccess},
|
||||
command_buffer::{
|
||||
AutoCommandBufferBuilder, BufferImageCopy, CommandBufferUsage, CopyImageToBufferInfo,
|
||||
SubpassContents,
|
||||
RenderPassBeginInfo, SubpassContents,
|
||||
},
|
||||
device::{
|
||||
physical::{PhysicalDevice, PhysicalDeviceType},
|
||||
@ -260,8 +260,6 @@ fn main() {
|
||||
.build(device.clone())
|
||||
.unwrap();
|
||||
|
||||
let clear_values = vec![[0.0, 0.0, 1.0, 1.0].into()];
|
||||
|
||||
let create_buffer = || {
|
||||
CpuAccessibleBuffer::from_iter(
|
||||
device.clone(),
|
||||
@ -285,7 +283,13 @@ fn main() {
|
||||
// drawing commands are broadcast to each view in the view mask of the active renderpass
|
||||
// which means only a single draw call is needed to draw to multiple layers of the framebuffer
|
||||
builder
|
||||
.begin_render_pass(framebuffer.clone(), SubpassContents::Inline, clear_values)
|
||||
.begin_render_pass(
|
||||
RenderPassBeginInfo {
|
||||
clear_values: vec![Some([0.0, 0.0, 1.0, 1.0].into())],
|
||||
..RenderPassBeginInfo::framebuffer(framebuffer.clone())
|
||||
},
|
||||
SubpassContents::Inline,
|
||||
)
|
||||
.unwrap()
|
||||
.bind_pipeline_graphics(pipeline.clone())
|
||||
.bind_vertex_buffers(0, vertex_buffer.clone())
|
||||
|
@ -15,7 +15,9 @@ use bytemuck::{Pod, Zeroable};
|
||||
use std::sync::Arc;
|
||||
use vulkano::{
|
||||
buffer::{BufferAccess, BufferUsage, CpuAccessibleBuffer},
|
||||
command_buffer::{AutoCommandBufferBuilder, CommandBufferUsage, SubpassContents},
|
||||
command_buffer::{
|
||||
AutoCommandBufferBuilder, CommandBufferUsage, RenderPassBeginInfo, SubpassContents,
|
||||
},
|
||||
device::{
|
||||
physical::{PhysicalDevice, PhysicalDeviceType},
|
||||
Device, DeviceCreateInfo, DeviceExtensions, DeviceOwned, QueueCreateInfo,
|
||||
@ -342,8 +344,6 @@ fn main() {
|
||||
recreate_swapchain = true;
|
||||
}
|
||||
|
||||
let clear_values = vec![[0.0, 0.0, 1.0, 1.0].into(), 1.0.into()];
|
||||
|
||||
let mut builder = AutoCommandBufferBuilder::primary(
|
||||
device.clone(),
|
||||
queue.family(),
|
||||
@ -361,9 +361,11 @@ fn main() {
|
||||
.set_viewport(0, [viewport.clone()])
|
||||
.bind_pipeline_graphics(pipeline.clone())
|
||||
.begin_render_pass(
|
||||
framebuffers[image_num].clone(),
|
||||
RenderPassBeginInfo {
|
||||
clear_values: vec![Some([0.0, 0.0, 1.0, 1.0].into()), Some(1.0.into())],
|
||||
..RenderPassBeginInfo::framebuffer(framebuffers[image_num].clone())
|
||||
},
|
||||
SubpassContents::Inline,
|
||||
clear_values,
|
||||
)
|
||||
.unwrap()
|
||||
// Begin query 0, then draw the red triangle.
|
||||
|
@ -11,7 +11,9 @@ use bytemuck::{Pod, Zeroable};
|
||||
use std::{io::Cursor, sync::Arc};
|
||||
use vulkano::{
|
||||
buffer::{BufferUsage, CpuAccessibleBuffer, TypedBufferAccess},
|
||||
command_buffer::{AutoCommandBufferBuilder, CommandBufferUsage, SubpassContents},
|
||||
command_buffer::{
|
||||
AutoCommandBufferBuilder, CommandBufferUsage, RenderPassBeginInfo, SubpassContents,
|
||||
},
|
||||
descriptor_set::WriteDescriptorSet,
|
||||
device::{
|
||||
physical::{PhysicalDevice, PhysicalDeviceType},
|
||||
@ -288,7 +290,6 @@ fn main() {
|
||||
recreate_swapchain = true;
|
||||
}
|
||||
|
||||
let clear_values = vec![[0.0, 0.0, 1.0, 1.0].into()];
|
||||
let mut builder = AutoCommandBufferBuilder::primary(
|
||||
device.clone(),
|
||||
queue.family(),
|
||||
@ -297,9 +298,11 @@ fn main() {
|
||||
.unwrap();
|
||||
builder
|
||||
.begin_render_pass(
|
||||
framebuffers[image_num].clone(),
|
||||
RenderPassBeginInfo {
|
||||
clear_values: vec![Some([0.0, 0.0, 1.0, 1.0].into())],
|
||||
..RenderPassBeginInfo::framebuffer(framebuffers[image_num].clone())
|
||||
},
|
||||
SubpassContents::Inline,
|
||||
clear_values,
|
||||
)
|
||||
.unwrap()
|
||||
.set_viewport(0, [viewport.clone()])
|
||||
|
@ -23,7 +23,9 @@ use bytemuck::{Pod, Zeroable};
|
||||
use std::{fs::File, io::Read, sync::Arc};
|
||||
use vulkano::{
|
||||
buffer::{BufferUsage, CpuAccessibleBuffer, TypedBufferAccess},
|
||||
command_buffer::{AutoCommandBufferBuilder, CommandBufferUsage, SubpassContents},
|
||||
command_buffer::{
|
||||
AutoCommandBufferBuilder, CommandBufferUsage, RenderPassBeginInfo, SubpassContents,
|
||||
},
|
||||
device::{
|
||||
physical::{PhysicalDevice, PhysicalDeviceType},
|
||||
Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo,
|
||||
@ -273,7 +275,6 @@ fn main() {
|
||||
recreate_swapchain = true;
|
||||
}
|
||||
|
||||
let clear_values = vec![[0.0, 0.0, 0.0, 1.0].into()];
|
||||
let mut builder = AutoCommandBufferBuilder::primary(
|
||||
device.clone(),
|
||||
queue.family(),
|
||||
@ -282,9 +283,11 @@ fn main() {
|
||||
.unwrap();
|
||||
builder
|
||||
.begin_render_pass(
|
||||
framebuffers[image_num].clone(),
|
||||
RenderPassBeginInfo {
|
||||
clear_values: vec![Some([0.0, 0.0, 0.0, 1.0].into())],
|
||||
..RenderPassBeginInfo::framebuffer(framebuffers[image_num].clone())
|
||||
},
|
||||
SubpassContents::Inline,
|
||||
clear_values,
|
||||
)
|
||||
.unwrap()
|
||||
.set_viewport(0, [viewport.clone()])
|
||||
|
@ -11,7 +11,9 @@ use bytemuck::{Pod, Zeroable};
|
||||
use std::{io::Cursor, sync::Arc};
|
||||
use vulkano::{
|
||||
buffer::{BufferUsage, CpuAccessibleBuffer, TypedBufferAccess},
|
||||
command_buffer::{AutoCommandBufferBuilder, CommandBufferUsage, SubpassContents},
|
||||
command_buffer::{
|
||||
AutoCommandBufferBuilder, CommandBufferUsage, RenderPassBeginInfo, SubpassContents,
|
||||
},
|
||||
descriptor_set::{
|
||||
layout::{
|
||||
DescriptorSetLayout, DescriptorSetLayoutCreateInfo, DescriptorSetLayoutCreationError,
|
||||
@ -425,7 +427,6 @@ fn main() {
|
||||
recreate_swapchain = true;
|
||||
}
|
||||
|
||||
let clear_values = vec![[0.0, 0.0, 1.0, 1.0].into()];
|
||||
let mut builder = AutoCommandBufferBuilder::primary(
|
||||
device.clone(),
|
||||
queue.family(),
|
||||
@ -434,9 +435,11 @@ fn main() {
|
||||
.unwrap();
|
||||
builder
|
||||
.begin_render_pass(
|
||||
framebuffers[image_num].clone(),
|
||||
RenderPassBeginInfo {
|
||||
clear_values: vec![Some([0.0, 0.0, 1.0, 1.0].into())],
|
||||
..RenderPassBeginInfo::framebuffer(framebuffers[image_num].clone())
|
||||
},
|
||||
SubpassContents::Inline,
|
||||
clear_values,
|
||||
)
|
||||
.unwrap()
|
||||
.set_viewport(0, [viewport.clone()])
|
||||
|
@ -12,7 +12,9 @@ use examples::{Normal, Vertex, INDICES, NORMALS, VERTICES};
|
||||
use std::{sync::Arc, time::Instant};
|
||||
use vulkano::{
|
||||
buffer::{BufferUsage, CpuAccessibleBuffer, CpuBufferPool, TypedBufferAccess},
|
||||
command_buffer::{AutoCommandBufferBuilder, CommandBufferUsage, SubpassContents},
|
||||
command_buffer::{
|
||||
AutoCommandBufferBuilder, CommandBufferUsage, RenderPassBeginInfo, SubpassContents,
|
||||
},
|
||||
descriptor_set::{PersistentDescriptorSet, WriteDescriptorSet},
|
||||
device::{
|
||||
physical::{PhysicalDevice, PhysicalDeviceType},
|
||||
@ -274,9 +276,14 @@ fn main() {
|
||||
.unwrap();
|
||||
builder
|
||||
.begin_render_pass(
|
||||
framebuffers[image_num].clone(),
|
||||
RenderPassBeginInfo {
|
||||
clear_values: vec![
|
||||
Some([0.0, 0.0, 1.0, 1.0].into()),
|
||||
Some(1f32.into()),
|
||||
],
|
||||
..RenderPassBeginInfo::framebuffer(framebuffers[image_num].clone())
|
||||
},
|
||||
SubpassContents::Inline,
|
||||
vec![[0.0, 0.0, 1.0, 1.0].into(), 1f32.into()],
|
||||
)
|
||||
.unwrap()
|
||||
.bind_pipeline_graphics(pipeline.clone())
|
||||
|
@ -22,7 +22,9 @@ use bytemuck::{Pod, Zeroable};
|
||||
use std::sync::Arc;
|
||||
use vulkano::{
|
||||
buffer::{BufferUsage, CpuAccessibleBuffer, TypedBufferAccess},
|
||||
command_buffer::{AutoCommandBufferBuilder, CommandBufferUsage, SubpassContents},
|
||||
command_buffer::{
|
||||
AutoCommandBufferBuilder, CommandBufferUsage, RenderPassBeginInfo, SubpassContents,
|
||||
},
|
||||
device::{
|
||||
physical::{PhysicalDevice, PhysicalDeviceType},
|
||||
Device, DeviceCreateInfo, DeviceExtensions, Features, QueueCreateInfo,
|
||||
@ -387,9 +389,11 @@ fn main() {
|
||||
.unwrap();
|
||||
builder
|
||||
.begin_render_pass(
|
||||
framebuffers[image_num].clone(),
|
||||
RenderPassBeginInfo {
|
||||
clear_values: vec![Some([0.0, 0.0, 0.0, 1.0].into())],
|
||||
..RenderPassBeginInfo::framebuffer(framebuffers[image_num].clone())
|
||||
},
|
||||
SubpassContents::Inline,
|
||||
vec![[0.0, 0.0, 0.0, 1.0].into()],
|
||||
)
|
||||
.unwrap()
|
||||
.set_viewport(0, [viewport.clone()])
|
||||
|
@ -11,7 +11,9 @@ use bytemuck::{Pod, Zeroable};
|
||||
use std::{io::Cursor, sync::Arc};
|
||||
use vulkano::{
|
||||
buffer::{BufferUsage, CpuAccessibleBuffer, TypedBufferAccess},
|
||||
command_buffer::{AutoCommandBufferBuilder, CommandBufferUsage, SubpassContents},
|
||||
command_buffer::{
|
||||
AutoCommandBufferBuilder, CommandBufferUsage, RenderPassBeginInfo, SubpassContents,
|
||||
},
|
||||
descriptor_set::{PersistentDescriptorSet, WriteDescriptorSet},
|
||||
device::{
|
||||
physical::{PhysicalDevice, PhysicalDeviceType},
|
||||
@ -297,7 +299,6 @@ fn main() {
|
||||
recreate_swapchain = true;
|
||||
}
|
||||
|
||||
let clear_values = vec![[0.0, 0.0, 1.0, 1.0].into()];
|
||||
let mut builder = AutoCommandBufferBuilder::primary(
|
||||
device.clone(),
|
||||
queue.family(),
|
||||
@ -306,9 +307,11 @@ fn main() {
|
||||
.unwrap();
|
||||
builder
|
||||
.begin_render_pass(
|
||||
framebuffers[image_num].clone(),
|
||||
RenderPassBeginInfo {
|
||||
clear_values: vec![Some([0.0, 0.0, 1.0, 1.0].into())],
|
||||
..RenderPassBeginInfo::framebuffer(framebuffers[image_num].clone())
|
||||
},
|
||||
SubpassContents::Inline,
|
||||
clear_values,
|
||||
)
|
||||
.unwrap()
|
||||
.set_viewport(0, [viewport.clone()])
|
||||
|
@ -20,7 +20,9 @@ use bytemuck::{Pod, Zeroable};
|
||||
use std::sync::Arc;
|
||||
use vulkano::{
|
||||
buffer::{BufferUsage, CpuAccessibleBuffer, TypedBufferAccess},
|
||||
command_buffer::{AutoCommandBufferBuilder, CommandBufferUsage, SubpassContents},
|
||||
command_buffer::{
|
||||
AutoCommandBufferBuilder, CommandBufferUsage, RenderPassBeginInfo, SubpassContents,
|
||||
},
|
||||
device::{
|
||||
physical::{PhysicalDevice, PhysicalDeviceType},
|
||||
Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo,
|
||||
@ -472,9 +474,6 @@ fn main() {
|
||||
recreate_swapchain = true;
|
||||
}
|
||||
|
||||
// Specify the color to clear the framebuffer with i.e. blue
|
||||
let clear_values = vec![[0.0, 0.0, 1.0, 1.0].into()];
|
||||
|
||||
// In order to draw, we have to build a *command buffer*. The command buffer object holds
|
||||
// the list of commands that are going to be executed.
|
||||
//
|
||||
@ -492,17 +491,22 @@ fn main() {
|
||||
.unwrap();
|
||||
|
||||
builder
|
||||
// Before we can draw, we have to *enter a render pass*. There are two methods to do
|
||||
// this: `draw_inline` and `draw_secondary`. The latter is a bit more advanced and is
|
||||
// not covered here.
|
||||
//
|
||||
// The third parameter builds the list of values to clear the attachments with. The API
|
||||
// is similar to the list of attachments when building the framebuffers, except that
|
||||
// only the attachments that use `load: Clear` appear in the list.
|
||||
// Before we can draw, we have to *enter a render pass*.
|
||||
.begin_render_pass(
|
||||
framebuffers[image_num].clone(),
|
||||
RenderPassBeginInfo {
|
||||
// A list of values to clear the attachments with. This list contains
|
||||
// one item for each attachment in the render pass. In this case,
|
||||
// there is only one attachment, and we clear it with a blue color.
|
||||
//
|
||||
// Only attachments that have `LoadOp::Clear` are provided with clear
|
||||
// values, any others should use `ClearValue::None` as the clear value.
|
||||
clear_values: vec![Some([0.0, 0.0, 1.0, 1.0].into())],
|
||||
..RenderPassBeginInfo::framebuffer(framebuffers[image_num].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,
|
||||
clear_values,
|
||||
)
|
||||
.unwrap()
|
||||
// We are now inside the first subpass of the render pass. We add a draw command.
|
||||
|
@ -38,11 +38,10 @@ use crate::{
|
||||
image::{sys::UnsafeImage, ImageAccess, ImageLayout, ImageSubresourceRange},
|
||||
pipeline::GraphicsPipeline,
|
||||
query::{QueryControlFlags, QueryPipelineStatisticFlags, QueryType},
|
||||
render_pass::Subpass,
|
||||
render_pass::{Framebuffer, Subpass},
|
||||
sync::{AccessCheckError, AccessFlags, GpuFuture, PipelineMemoryAccess, PipelineStages},
|
||||
DeviceSize, OomError,
|
||||
};
|
||||
use smallvec::SmallVec;
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
error, fmt,
|
||||
@ -85,9 +84,9 @@ pub struct AutoCommandBufferBuilder<L, P = StandardCommandPoolBuilder> {
|
||||
pub(super) struct RenderPassState {
|
||||
pub(super) subpass: Subpass,
|
||||
pub(super) contents: SubpassContents,
|
||||
pub(super) attached_layers_ranges: SmallVec<[Range<u32>; 4]>,
|
||||
pub(super) extent: [u32; 2],
|
||||
pub(super) framebuffer: ash::vk::Framebuffer, // Always null for secondary command buffers
|
||||
pub(super) render_area_offset: [u32; 2],
|
||||
pub(super) render_area_extent: [u32; 2],
|
||||
pub(super) framebuffer: Option<Arc<Framebuffer>>, // In a secondary command buffer, this is only known if provided with the inheritance info.
|
||||
}
|
||||
|
||||
// The state of an active query.
|
||||
@ -286,15 +285,22 @@ impl<L> AutoCommandBufferBuilder<L, StandardCommandPoolBuilder> {
|
||||
|CommandBufferInheritanceRenderPassInfo {
|
||||
subpass,
|
||||
framebuffer,
|
||||
}| RenderPassState {
|
||||
subpass: subpass.clone(),
|
||||
contents: SubpassContents::Inline,
|
||||
extent: framebuffer.as_ref().map(|f| f.extent()).unwrap_or_default(),
|
||||
attached_layers_ranges: framebuffer
|
||||
}| {
|
||||
// In a secondary command buffer, we don't know the render area yet, so use a
|
||||
// dummy value.
|
||||
let render_area_offset = [0, 0];
|
||||
let render_area_extent = framebuffer
|
||||
.as_ref()
|
||||
.map(|f| f.attached_layers_ranges())
|
||||
.unwrap_or_default(),
|
||||
framebuffer: ash::vk::Framebuffer::null(), // Only needed for primary command buffers
|
||||
.map(|f| f.extent())
|
||||
.unwrap_or([u32::MAX, u32::MAX]);
|
||||
|
||||
RenderPassState {
|
||||
subpass: subpass.clone(),
|
||||
contents: SubpassContents::Inline,
|
||||
render_area_offset,
|
||||
render_area_extent,
|
||||
framebuffer: framebuffer.clone(),
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
@ -785,11 +791,6 @@ err_gen!(BuildError {
|
||||
OomError,
|
||||
});
|
||||
|
||||
err_gen!(BeginRenderPassError {
|
||||
AutoCommandBufferBuilderContextError,
|
||||
SyncCommandBufferBuilderError,
|
||||
});
|
||||
|
||||
err_gen!(CopyQueryPoolResultsError {
|
||||
AutoCommandBufferBuilderContextError,
|
||||
CheckCopyQueryPoolResultsError,
|
||||
@ -884,80 +885,6 @@ err_gen!(ResetQueryPoolError {
|
||||
CheckResetQueryPoolError,
|
||||
});
|
||||
|
||||
/// Errors that can happen when calling [`clear_attachments`](AutoCommandBufferBuilder::clear_attachments)
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub enum ClearAttachmentsError {
|
||||
/// AutoCommandBufferBuilderContextError
|
||||
AutoCommandBufferBuilderContextError(AutoCommandBufferBuilderContextError),
|
||||
/// CheckPipelineError
|
||||
CheckPipelineError(CheckPipelineError),
|
||||
|
||||
/// The index of the color attachment is not present
|
||||
InvalidColorAttachmentIndex(u32),
|
||||
/// There is no depth/stencil attachment present
|
||||
DepthStencilAttachmentNotPresent,
|
||||
/// The clear rect cannot have extent of `0`
|
||||
ZeroRectExtent,
|
||||
/// The layer count cannot be `0`
|
||||
ZeroLayerCount,
|
||||
/// The clear rect region must be inside the render area of the render pass
|
||||
RectOutOfBounds,
|
||||
/// The clear rect's layers must be inside the layers ranges for all the attachments
|
||||
LayersOutOfBounds,
|
||||
/// If the render pass instance this is recorded in uses multiview,
|
||||
/// then `ClearRect.base_array_layer` must be zero and `ClearRect.layer_count` must be one
|
||||
InvalidMultiviewLayerRange,
|
||||
}
|
||||
|
||||
impl error::Error for ClearAttachmentsError {}
|
||||
|
||||
impl fmt::Display for ClearAttachmentsError {
|
||||
#[inline]
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
||||
match *self {
|
||||
ClearAttachmentsError::AutoCommandBufferBuilderContextError(e) => write!(fmt, "{}", e)?,
|
||||
ClearAttachmentsError::CheckPipelineError(e) => write!(fmt, "{}", e)?,
|
||||
ClearAttachmentsError::InvalidColorAttachmentIndex(index) => {
|
||||
write!(fmt, "Color attachment {} is not present", index)?
|
||||
}
|
||||
ClearAttachmentsError::DepthStencilAttachmentNotPresent => {
|
||||
write!(fmt, "There is no depth/stencil attachment present")?
|
||||
}
|
||||
ClearAttachmentsError::ZeroRectExtent => {
|
||||
write!(fmt, "The clear rect cannot have extent of 0")?
|
||||
}
|
||||
ClearAttachmentsError::ZeroLayerCount => write!(fmt, "The layer count cannot be 0")?,
|
||||
ClearAttachmentsError::RectOutOfBounds => write!(
|
||||
fmt,
|
||||
"The clear rect region must be inside the render area of the render pass"
|
||||
)?,
|
||||
ClearAttachmentsError::LayersOutOfBounds => write!(
|
||||
fmt,
|
||||
"The clear rect's layers must be inside the layers ranges for all the attachments"
|
||||
)?,
|
||||
ClearAttachmentsError::InvalidMultiviewLayerRange => write!(
|
||||
fmt,
|
||||
"If the render pass instance this is recorded in uses multiview, then `ClearRect.base_array_layer` must be zero and `ClearRect.layer_count` must be one"
|
||||
)?,
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<AutoCommandBufferBuilderContextError> for ClearAttachmentsError {
|
||||
#[inline]
|
||||
fn from(err: AutoCommandBufferBuilderContextError) -> ClearAttachmentsError {
|
||||
ClearAttachmentsError::AutoCommandBufferBuilderContextError(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<CheckPipelineError> for ClearAttachmentsError {
|
||||
#[inline]
|
||||
fn from(err: CheckPipelineError) -> ClearAttachmentsError {
|
||||
ClearAttachmentsError::CheckPipelineError(err)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub enum AutoCommandBufferBuilderContextError {
|
||||
/// Operation forbidden inside of a render pass.
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -170,7 +170,7 @@ where
|
||||
// Framebuffer, if present on the secondary command buffer, must be the
|
||||
// same as the one in the current render pass.
|
||||
if let Some(framebuffer) = &render_pass.framebuffer {
|
||||
if framebuffer.internal_object() != render_pass_state.framebuffer {
|
||||
if Some(framebuffer) != render_pass_state.framebuffer.as_ref() {
|
||||
return Err(AutoCommandBufferBuilderContextError::IncompatibleFramebuffer);
|
||||
}
|
||||
}
|
||||
|
@ -91,6 +91,7 @@ pub use self::commands::{
|
||||
CheckBeginQueryError, CheckCopyQueryPoolResultsError, CheckEndQueryError,
|
||||
CheckResetQueryPoolError, CheckWriteTimestampError,
|
||||
},
|
||||
render_pass::{ClearAttachment, ClearRect, RenderPassBeginInfo, RenderPassError},
|
||||
transfer::{
|
||||
BufferCopy, BufferImageCopy, CopyBufferInfo, CopyBufferInfoTyped, CopyBufferToImageInfo,
|
||||
CopyImageInfo, CopyImageToBufferInfo, FillBufferInfo, ImageCopy,
|
||||
@ -100,11 +101,10 @@ pub use self::commands::{
|
||||
pub use self::{
|
||||
auto::{
|
||||
AutoCommandBufferBuilder, AutoCommandBufferBuilderContextError, BeginError,
|
||||
BeginQueryError, BeginRenderPassError, BuildError, CopyQueryPoolResultsError,
|
||||
DispatchError, DispatchIndirectError, DrawError, DrawIndexedError,
|
||||
DrawIndexedIndirectError, DrawIndirectError, EndQueryError, ExecuteCommandsError,
|
||||
PrimaryAutoCommandBuffer, ResetQueryPoolError, SecondaryAutoCommandBuffer,
|
||||
WriteTimestampError,
|
||||
BeginQueryError, BuildError, CopyQueryPoolResultsError, DispatchError,
|
||||
DispatchIndirectError, DrawError, DrawIndexedError, DrawIndexedIndirectError,
|
||||
DrawIndirectError, EndQueryError, ExecuteCommandsError, PrimaryAutoCommandBuffer,
|
||||
ResetQueryPoolError, SecondaryAutoCommandBuffer, WriteTimestampError,
|
||||
},
|
||||
traits::{
|
||||
CommandBufferExecError, CommandBufferExecFuture, PrimaryCommandBuffer,
|
||||
|
@ -8,7 +8,7 @@
|
||||
// according to those terms.
|
||||
|
||||
pub use super::commands::{
|
||||
bind_push::UnsafeCommandBufferBuilderBindVertexBuffer, render_pass::RenderPassBeginInfo,
|
||||
bind_push::UnsafeCommandBufferBuilderBindVertexBuffer,
|
||||
secondary::UnsafeCommandBufferBuilderExecuteCommands,
|
||||
};
|
||||
use super::{
|
||||
|
@ -159,41 +159,6 @@ impl Format {
|
||||
| Format::R8_UINT
|
||||
)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn decode_clear_value(&self, value: ClearValue) -> ClearValue {
|
||||
let aspects = self.aspects();
|
||||
|
||||
if aspects.depth && aspects.stencil {
|
||||
assert!(matches!(value, ClearValue::DepthStencil(_)));
|
||||
} else if aspects.depth {
|
||||
assert!(matches!(value, ClearValue::Depth(_)));
|
||||
} else if aspects.stencil {
|
||||
assert!(matches!(value, ClearValue::Stencil(_)));
|
||||
} else if let Some(numeric_type) = self.type_color() {
|
||||
match numeric_type {
|
||||
NumericType::SFLOAT
|
||||
| NumericType::UFLOAT
|
||||
| NumericType::SNORM
|
||||
| NumericType::UNORM
|
||||
| NumericType::SSCALED
|
||||
| NumericType::USCALED
|
||||
| NumericType::SRGB => {
|
||||
assert!(matches!(value, ClearValue::Float(_)));
|
||||
}
|
||||
NumericType::SINT => {
|
||||
assert!(matches!(value, ClearValue::Int(_)));
|
||||
}
|
||||
NumericType::UINT => {
|
||||
assert!(matches!(value, ClearValue::Uint(_)));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
panic!("Shouldn't happen!");
|
||||
}
|
||||
|
||||
value
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Format> for ash::vk::Format {
|
||||
@ -421,25 +386,67 @@ pub(crate) enum FormatCompatibilityInner {
|
||||
}
|
||||
|
||||
/// Describes a uniform value that will be used to fill an image.
|
||||
// TODO: should have the same layout as `vk::ClearValue` for performance
|
||||
#[derive(Debug, Copy, Clone, PartialEq)]
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
pub enum ClearValue {
|
||||
/// Entry for attachments that aren't cleared.
|
||||
None,
|
||||
/// Value for floating-point attachments, including `UNORM`, `SNORM`, `SFLOAT`.
|
||||
Float([f32; 4]),
|
||||
|
||||
/// Value for integer attachments, including `SINT`.
|
||||
Int([i32; 4]),
|
||||
|
||||
/// Value for unsigned integer attachments, including `UINT`.
|
||||
Uint([u32; 4]),
|
||||
|
||||
/// Value for depth attachments.
|
||||
Depth(f32),
|
||||
|
||||
/// Value for stencil attachments.
|
||||
Stencil(u32),
|
||||
|
||||
/// Value for depth and stencil attachments.
|
||||
DepthStencil((f32, u32)),
|
||||
}
|
||||
|
||||
impl From<ClearValue> for ash::vk::ClearValue {
|
||||
#[inline]
|
||||
fn from(val: ClearValue) -> Self {
|
||||
match val {
|
||||
ClearValue::Float(val) => Self {
|
||||
color: ash::vk::ClearColorValue { float32: val },
|
||||
},
|
||||
ClearValue::Int(val) => Self {
|
||||
color: ash::vk::ClearColorValue { int32: val },
|
||||
},
|
||||
ClearValue::Uint(val) => Self {
|
||||
color: ash::vk::ClearColorValue { uint32: val },
|
||||
},
|
||||
ClearValue::Depth(depth) => Self {
|
||||
depth_stencil: ash::vk::ClearDepthStencilValue { depth, stencil: 0 },
|
||||
},
|
||||
ClearValue::Stencil(stencil) => Self {
|
||||
depth_stencil: ash::vk::ClearDepthStencilValue {
|
||||
depth: 0.0,
|
||||
stencil,
|
||||
},
|
||||
},
|
||||
ClearValue::DepthStencil((depth, stencil)) => Self {
|
||||
depth_stencil: ash::vk::ClearDepthStencilValue { depth, stencil },
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ClearColorValue> for ClearValue {
|
||||
#[inline]
|
||||
fn from(val: ClearColorValue) -> Self {
|
||||
match val {
|
||||
ClearColorValue::Float(val) => Self::Float(val),
|
||||
ClearColorValue::Int(val) => Self::Int(val),
|
||||
ClearColorValue::Uint(val) => Self::Uint(val),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<[f32; 1]> for ClearValue {
|
||||
#[inline]
|
||||
fn from(val: [f32; 1]) -> Self {
|
||||
|
@ -8,14 +8,12 @@
|
||||
// according to those terms.
|
||||
|
||||
use super::{
|
||||
sys::UnsafeImage,
|
||||
traits::{ImageClearValue, ImageContent},
|
||||
ImageAccess, ImageCreationError, ImageDescriptorLayouts, ImageInner, ImageLayout, ImageUsage,
|
||||
SampleCount,
|
||||
sys::UnsafeImage, traits::ImageContent, ImageAccess, ImageCreationError,
|
||||
ImageDescriptorLayouts, ImageInner, ImageLayout, ImageUsage, SampleCount,
|
||||
};
|
||||
use crate::{
|
||||
device::{Device, DeviceOwned},
|
||||
format::{ClearValue, Format},
|
||||
format::Format,
|
||||
image::{sys::UnsafeImageCreateInfo, ImageDimensions},
|
||||
memory::{
|
||||
pool::{
|
||||
@ -603,16 +601,6 @@ unsafe impl<A> DeviceOwned for AttachmentImage<A> {
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<A> ImageClearValue<ClearValue> for AttachmentImage<A>
|
||||
where
|
||||
A: MemoryPoolAlloc,
|
||||
{
|
||||
#[inline]
|
||||
fn decode(&self, value: ClearValue) -> Option<ClearValue> {
|
||||
Some(self.format.decode_clear_value(value))
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<P, A> ImageContent<P> for AttachmentImage<A>
|
||||
where
|
||||
A: MemoryPoolAlloc,
|
||||
@ -645,74 +633,6 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
/// Clear attachment type, used in [`clear_attachments`](crate::command_buffer::AutoCommandBufferBuilder::clear_attachments) command.
|
||||
pub enum ClearAttachment {
|
||||
/// Clear the color attachment at the specified index, with the specified clear value.
|
||||
Color(ClearValue, u32),
|
||||
/// Clear the depth attachment with the speficied depth value.
|
||||
Depth(f32),
|
||||
/// Clear the stencil attachment with the speficied stencil value.
|
||||
Stencil(u32),
|
||||
/// Clear the depth and stencil attachments with the speficied depth and stencil values.
|
||||
DepthStencil((f32, u32)),
|
||||
}
|
||||
|
||||
impl From<ClearAttachment> for ash::vk::ClearAttachment {
|
||||
fn from(v: ClearAttachment) -> Self {
|
||||
match v {
|
||||
ClearAttachment::Color(clear_value, color_attachment) => ash::vk::ClearAttachment {
|
||||
aspect_mask: ash::vk::ImageAspectFlags::COLOR,
|
||||
color_attachment,
|
||||
clear_value: ash::vk::ClearValue {
|
||||
color: match clear_value {
|
||||
ClearValue::Float(val) => ash::vk::ClearColorValue { float32: val },
|
||||
ClearValue::Int(val) => ash::vk::ClearColorValue { int32: val },
|
||||
ClearValue::Uint(val) => ash::vk::ClearColorValue { uint32: val },
|
||||
_ => ash::vk::ClearColorValue { float32: [0.0; 4] },
|
||||
},
|
||||
},
|
||||
},
|
||||
ClearAttachment::Depth(depth) => ash::vk::ClearAttachment {
|
||||
aspect_mask: ash::vk::ImageAspectFlags::DEPTH,
|
||||
color_attachment: 0,
|
||||
clear_value: ash::vk::ClearValue {
|
||||
depth_stencil: ash::vk::ClearDepthStencilValue { depth, stencil: 0 },
|
||||
},
|
||||
},
|
||||
ClearAttachment::Stencil(stencil) => ash::vk::ClearAttachment {
|
||||
aspect_mask: ash::vk::ImageAspectFlags::STENCIL,
|
||||
color_attachment: 0,
|
||||
clear_value: ash::vk::ClearValue {
|
||||
depth_stencil: ash::vk::ClearDepthStencilValue {
|
||||
depth: 0.0,
|
||||
stencil,
|
||||
},
|
||||
},
|
||||
},
|
||||
ClearAttachment::DepthStencil((depth, stencil)) => ash::vk::ClearAttachment {
|
||||
aspect_mask: ash::vk::ImageAspectFlags::DEPTH | ash::vk::ImageAspectFlags::STENCIL,
|
||||
color_attachment: 0,
|
||||
clear_value: ash::vk::ClearValue {
|
||||
depth_stencil: ash::vk::ClearDepthStencilValue { depth, stencil },
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Specifies the clear region for the [`clear_attachments`](crate::command_buffer::AutoCommandBufferBuilder::clear_attachments) command.
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct ClearRect {
|
||||
/// The rectangle offset.
|
||||
pub rect_offset: [u32; 2],
|
||||
/// The width and height of the rectangle.
|
||||
pub rect_extent: [u32; 2],
|
||||
/// The first layer to be cleared.
|
||||
pub base_array_layer: u32,
|
||||
/// The number of layers to be cleared.
|
||||
pub layer_count: u32,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::AttachmentImage;
|
||||
|
@ -8,14 +8,12 @@
|
||||
// according to those terms.
|
||||
|
||||
use super::{
|
||||
sys::UnsafeImage,
|
||||
traits::{ImageClearValue, ImageContent},
|
||||
ImageAccess, ImageCreateFlags, ImageCreationError, ImageDescriptorLayouts, ImageDimensions,
|
||||
ImageInner, ImageLayout, ImageUsage,
|
||||
sys::UnsafeImage, traits::ImageContent, ImageAccess, ImageCreateFlags, ImageCreationError,
|
||||
ImageDescriptorLayouts, ImageDimensions, ImageInner, ImageLayout, ImageUsage,
|
||||
};
|
||||
use crate::{
|
||||
device::{physical::QueueFamily, Device, DeviceOwned},
|
||||
format::{ClearValue, Format},
|
||||
format::Format,
|
||||
image::sys::UnsafeImageCreateInfo,
|
||||
memory::{
|
||||
pool::{
|
||||
@ -284,16 +282,6 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<A> ImageClearValue<ClearValue> for StorageImage<A>
|
||||
where
|
||||
A: MemoryPool,
|
||||
{
|
||||
#[inline]
|
||||
fn decode(&self, value: ClearValue) -> Option<ClearValue> {
|
||||
Some(self.format.decode_clear_value(value))
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<P, A> ImageContent<P> for StorageImage<A>
|
||||
where
|
||||
A: MemoryPool,
|
||||
|
@ -7,13 +7,9 @@
|
||||
// notice may not be copied, modified, or distributed except
|
||||
// according to those terms.
|
||||
|
||||
use super::{
|
||||
traits::{ImageClearValue, ImageContent},
|
||||
ImageAccess, ImageDescriptorLayouts, ImageInner, ImageLayout,
|
||||
};
|
||||
use super::{traits::ImageContent, ImageAccess, ImageDescriptorLayouts, ImageInner, ImageLayout};
|
||||
use crate::{
|
||||
device::{Device, DeviceOwned},
|
||||
format::ClearValue,
|
||||
swapchain::Swapchain,
|
||||
OomError,
|
||||
};
|
||||
@ -126,16 +122,6 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<W> ImageClearValue<ClearValue> for SwapchainImage<W>
|
||||
where
|
||||
W: Send + Sync,
|
||||
{
|
||||
#[inline]
|
||||
fn decode(&self, value: ClearValue) -> Option<ClearValue> {
|
||||
Some(self.swapchain.image_format().decode_clear_value(value))
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<P, W> ImageContent<P> for SwapchainImage<W>
|
||||
where
|
||||
W: Send + Sync,
|
||||
|
@ -13,7 +13,7 @@ use super::{
|
||||
};
|
||||
use crate::{
|
||||
device::{Device, DeviceOwned},
|
||||
format::{ClearValue, Format, FormatFeatures},
|
||||
format::{Format, FormatFeatures},
|
||||
SafeDeref,
|
||||
};
|
||||
use std::{
|
||||
@ -315,13 +315,6 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
/// Extension trait for images. Checks whether the value `T` can be used as a clear value for the
|
||||
/// given image.
|
||||
// TODO: isn't that for image views instead?
|
||||
pub unsafe trait ImageClearValue<T>: ImageAccess {
|
||||
fn decode(&self, value: T) -> Option<ClearValue>;
|
||||
}
|
||||
|
||||
pub unsafe trait ImageContent<P>: ImageAccess {
|
||||
/// Checks whether pixels of type `P` match the format of the image.
|
||||
fn matches_format(&self) -> bool;
|
||||
|
@ -76,41 +76,28 @@ impl RenderPass {
|
||||
.potential_format_features(),
|
||||
);
|
||||
|
||||
if aspects.color {
|
||||
// VUID-VkAttachmentDescription2-format-03294
|
||||
if matches!(
|
||||
initial_layout,
|
||||
for layout in [initial_layout, final_layout] {
|
||||
match layout {
|
||||
ImageLayout::ColorAttachmentOptimal => {
|
||||
// VUID-VkAttachmentDescription2-format-03295
|
||||
// VUID-VkAttachmentDescription2-format-03297
|
||||
if aspects.depth || aspects.stencil {
|
||||
return Err(RenderPassCreationError::AttachmentLayoutInvalid {
|
||||
attachment: atch_num,
|
||||
});
|
||||
}
|
||||
}
|
||||
ImageLayout::DepthStencilAttachmentOptimal
|
||||
| ImageLayout::DepthStencilReadOnlyOptimal
|
||||
) {
|
||||
return Err(RenderPassCreationError::AttachmentLayoutInvalid {
|
||||
attachment: atch_num,
|
||||
});
|
||||
}
|
||||
|
||||
// VUID-VkAttachmentDescription2-format-03296
|
||||
if matches!(
|
||||
final_layout,
|
||||
ImageLayout::DepthStencilAttachmentOptimal
|
||||
| ImageLayout::DepthStencilReadOnlyOptimal
|
||||
) {
|
||||
return Err(RenderPassCreationError::AttachmentLayoutInvalid {
|
||||
attachment: atch_num,
|
||||
});
|
||||
}
|
||||
} else if aspects.depth || aspects.stencil {
|
||||
// VUID-VkAttachmentDescription2-format-03295
|
||||
if matches!(initial_layout, ImageLayout::ColorAttachmentOptimal) {
|
||||
return Err(RenderPassCreationError::AttachmentLayoutInvalid {
|
||||
attachment: atch_num,
|
||||
});
|
||||
}
|
||||
|
||||
// VUID-VkAttachmentDescription2-format-03297
|
||||
if matches!(final_layout, ImageLayout::ColorAttachmentOptimal) {
|
||||
return Err(RenderPassCreationError::AttachmentLayoutInvalid {
|
||||
attachment: atch_num,
|
||||
});
|
||||
| ImageLayout::DepthStencilReadOnlyOptimal => {
|
||||
// VUID-VkAttachmentDescription2-format-03294
|
||||
// VUID-VkAttachmentDescription2-format-03296
|
||||
if aspects.color {
|
||||
return Err(RenderPassCreationError::AttachmentLayoutInvalid {
|
||||
attachment: atch_num,
|
||||
});
|
||||
}
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -37,6 +37,7 @@ use crate::{
|
||||
sync::{AccessFlags, PipelineStages},
|
||||
Version, VulkanObject,
|
||||
};
|
||||
use std::cmp::max;
|
||||
use std::{
|
||||
hash::{Hash, Hasher},
|
||||
mem::MaybeUninit,
|
||||
@ -243,22 +244,195 @@ impl RenderPass {
|
||||
}
|
||||
|
||||
/// Returns `true` if this render pass is compatible with the other render pass,
|
||||
/// as defined in the `Render Pass Compatibility` section of the Vulkan specs.
|
||||
// TODO: return proper error
|
||||
/// as defined in the [`Render Pass Compatibility` section of the Vulkan specs](https://www.khronos.org/registry/vulkan/specs/1.3-extensions/html/chap8.html#renderpass-compatibility).
|
||||
pub fn is_compatible_with(&self, other: &RenderPass) -> bool {
|
||||
if self.attachments().len() != other.attachments().len() {
|
||||
if self == other {
|
||||
return true;
|
||||
}
|
||||
|
||||
let Self {
|
||||
handle: _,
|
||||
device: _,
|
||||
attachments: attachments1,
|
||||
subpasses: subpasses1,
|
||||
dependencies: dependencies1,
|
||||
correlated_view_masks: correlated_view_masks1,
|
||||
granularity: _,
|
||||
views_used: _,
|
||||
} = self;
|
||||
let Self {
|
||||
handle: _,
|
||||
device: _,
|
||||
attachments: attachments2,
|
||||
subpasses: subpasses2,
|
||||
dependencies: dependencies2,
|
||||
correlated_view_masks: correlated_view_masks2,
|
||||
granularity: _,
|
||||
views_used: _,
|
||||
} = other;
|
||||
|
||||
if attachments1.len() != attachments2.len() {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (my_atch, other_atch) in self.attachments.iter().zip(other.attachments.iter()) {
|
||||
if !my_atch.is_compatible_with(&other_atch) {
|
||||
return false;
|
||||
}
|
||||
if !attachments1
|
||||
.iter()
|
||||
.zip(attachments2)
|
||||
.all(|(attachment_desc1, attachment_desc2)| {
|
||||
let AttachmentDescription {
|
||||
format: format1,
|
||||
samples: samples1,
|
||||
load_op: _,
|
||||
store_op: _,
|
||||
stencil_load_op: _,
|
||||
stencil_store_op: _,
|
||||
initial_layout: _,
|
||||
final_layout: _,
|
||||
_ne: _,
|
||||
} = attachment_desc1;
|
||||
let AttachmentDescription {
|
||||
format: format2,
|
||||
samples: samples2,
|
||||
load_op: _,
|
||||
store_op: _,
|
||||
stencil_load_op: _,
|
||||
stencil_store_op: _,
|
||||
initial_layout: _,
|
||||
final_layout: _,
|
||||
_ne: _,
|
||||
} = attachment_desc2;
|
||||
|
||||
format1 == format2 && samples1 == samples2
|
||||
})
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
let are_atch_refs_compatible = |atch_ref1, atch_ref2| match (atch_ref1, atch_ref2) {
|
||||
(None, None) => true,
|
||||
(Some(atch_ref1), Some(atch_ref2)) => {
|
||||
let &AttachmentReference {
|
||||
attachment: attachment1,
|
||||
layout: _,
|
||||
aspects: aspects1,
|
||||
_ne: _,
|
||||
} = atch_ref1;
|
||||
let AttachmentDescription {
|
||||
format: format1,
|
||||
samples: samples1,
|
||||
load_op: _,
|
||||
store_op: _,
|
||||
stencil_load_op: _,
|
||||
stencil_store_op: _,
|
||||
initial_layout: _,
|
||||
final_layout: _,
|
||||
_ne: _,
|
||||
} = &attachments1[attachment1 as usize];
|
||||
|
||||
// FIXME: finish
|
||||
let &AttachmentReference {
|
||||
attachment: attachment2,
|
||||
layout: _,
|
||||
aspects: aspects2,
|
||||
_ne: _,
|
||||
} = atch_ref2;
|
||||
let AttachmentDescription {
|
||||
format: format2,
|
||||
samples: samples2,
|
||||
load_op: _,
|
||||
store_op: _,
|
||||
stencil_load_op: _,
|
||||
stencil_store_op: _,
|
||||
initial_layout: _,
|
||||
final_layout: _,
|
||||
_ne: _,
|
||||
} = &attachments2[attachment2 as usize];
|
||||
|
||||
format1 == format2 && samples1 == samples2 && aspects1 == aspects2
|
||||
}
|
||||
_ => false,
|
||||
};
|
||||
|
||||
if subpasses1.len() != subpasses2.len() {
|
||||
return false;
|
||||
}
|
||||
|
||||
if !(subpasses1.iter())
|
||||
.zip(subpasses2.iter())
|
||||
.all(|(subpass1, subpass2)| {
|
||||
let &SubpassDescription {
|
||||
view_mask: view_mask1,
|
||||
input_attachments: ref input_attachments1,
|
||||
color_attachments: ref color_attachments1,
|
||||
resolve_attachments: ref resolve_attachments1,
|
||||
depth_stencil_attachment: ref depth_stencil_attachment1,
|
||||
preserve_attachments: _,
|
||||
_ne: _,
|
||||
} = subpass1;
|
||||
let &SubpassDescription {
|
||||
view_mask: view_mask2,
|
||||
input_attachments: ref input_attachments2,
|
||||
color_attachments: ref color_attachments2,
|
||||
resolve_attachments: ref resolve_attachments2,
|
||||
depth_stencil_attachment: ref depth_stencil_attachment2,
|
||||
preserve_attachments: _,
|
||||
_ne: _,
|
||||
} = subpass2;
|
||||
|
||||
if !(0..max(input_attachments1.len(), input_attachments2.len())).all(|i| {
|
||||
are_atch_refs_compatible(
|
||||
input_attachments1.get(i).and_then(|x| x.as_ref()),
|
||||
input_attachments2.get(i).and_then(|x| x.as_ref()),
|
||||
)
|
||||
}) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if !(0..max(color_attachments1.len(), color_attachments2.len())).all(|i| {
|
||||
are_atch_refs_compatible(
|
||||
color_attachments1.get(i).and_then(|x| x.as_ref()),
|
||||
color_attachments2.get(i).and_then(|x| x.as_ref()),
|
||||
)
|
||||
}) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if subpasses1.len() > 1
|
||||
&& !(0..max(resolve_attachments1.len(), resolve_attachments2.len())).all(|i| {
|
||||
are_atch_refs_compatible(
|
||||
resolve_attachments1.get(i).and_then(|x| x.as_ref()),
|
||||
resolve_attachments2.get(i).and_then(|x| x.as_ref()),
|
||||
)
|
||||
})
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if !are_atch_refs_compatible(
|
||||
depth_stencil_attachment1.as_ref(),
|
||||
depth_stencil_attachment2.as_ref(),
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if view_mask1 != view_mask2 {
|
||||
return false;
|
||||
}
|
||||
|
||||
true
|
||||
})
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if dependencies1 != dependencies2 {
|
||||
return false;
|
||||
}
|
||||
|
||||
if correlated_view_masks1 != correlated_view_masks2 {
|
||||
return false;
|
||||
}
|
||||
|
||||
true
|
||||
}
|
||||
|
||||
/// Returns `true` if the subpass of this description is compatible with the shader's fragment
|
||||
@ -384,6 +558,18 @@ impl Subpass {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the render pass of this subpass.
|
||||
#[inline]
|
||||
pub fn render_pass(&self) -> &Arc<RenderPass> {
|
||||
&self.render_pass
|
||||
}
|
||||
|
||||
/// Returns the index of this subpass within the renderpass.
|
||||
#[inline]
|
||||
pub fn index(&self) -> u32 {
|
||||
self.subpass_id
|
||||
}
|
||||
|
||||
/// Returns the subpass description for this subpass.
|
||||
#[inline]
|
||||
pub fn subpass_desc(&self) -> &SubpassDescription {
|
||||
@ -391,23 +577,22 @@ impl Subpass {
|
||||
}
|
||||
|
||||
/// Returns whether this subpass is the last one in the render pass. If `true` is returned,
|
||||
/// `next_subpass` will return `None`.
|
||||
/// calling `next_subpass` will panic.
|
||||
#[inline]
|
||||
pub fn is_last_subpass(&self) -> bool {
|
||||
self.subpass_id as usize == self.render_pass.subpasses().len() - 1
|
||||
}
|
||||
|
||||
/// Tries to advance to the next subpass after this one, and returns `true` if successful.
|
||||
/// Advances to the next subpass after this one.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// - Panics if there are no more render passes.
|
||||
#[inline]
|
||||
pub fn try_next_subpass(&mut self) -> bool {
|
||||
pub fn next_subpass(&mut self) {
|
||||
let next_id = self.subpass_id + 1;
|
||||
|
||||
if (next_id as usize) < self.render_pass.subpasses().len() {
|
||||
self.subpass_id = next_id;
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
assert!((next_id as usize) < self.render_pass.subpasses().len());
|
||||
self.subpass_id = next_id;
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@ -490,30 +675,6 @@ impl Subpass {
|
||||
.map_or(false, |f| f.aspects().stencil)
|
||||
}
|
||||
|
||||
/// Returns true if the subpass has any depth/stencil attachment.
|
||||
#[inline]
|
||||
pub fn has_depth_stencil_attachment(&self) -> bool {
|
||||
let subpass_desc = self.subpass_desc();
|
||||
match &subpass_desc.depth_stencil_attachment {
|
||||
Some(atch_ref) => true,
|
||||
None => false,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns true if the subpass has any color or depth/stencil attachment.
|
||||
#[inline]
|
||||
pub fn has_color_or_depth_stencil_attachment(&self) -> bool {
|
||||
if self.num_color_attachments() >= 1 {
|
||||
return true;
|
||||
}
|
||||
|
||||
let subpass_desc = self.subpass_desc();
|
||||
match &subpass_desc.depth_stencil_attachment {
|
||||
Some(atch_ref) => true,
|
||||
None => false,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the number of samples in the color and/or depth/stencil attachments. Returns `None`
|
||||
/// if there is no such attachment in this subpass.
|
||||
#[inline]
|
||||
@ -535,18 +696,6 @@ impl Subpass {
|
||||
.map(|atch_desc| atch_desc.samples)
|
||||
}
|
||||
|
||||
/// Returns the render pass of this subpass.
|
||||
#[inline]
|
||||
pub fn render_pass(&self) -> &Arc<RenderPass> {
|
||||
&self.render_pass
|
||||
}
|
||||
|
||||
/// Returns the index of this subpass within the renderpass.
|
||||
#[inline]
|
||||
pub fn index(&self) -> u32 {
|
||||
self.subpass_id
|
||||
}
|
||||
|
||||
/// Returns `true` if this subpass is compatible with the fragment output definition.
|
||||
// TODO: return proper error
|
||||
pub fn is_compatible_with(&self, shader_interface: &ShaderInterface) -> bool {
|
||||
@ -682,15 +831,6 @@ impl Default for AttachmentDescription {
|
||||
}
|
||||
}
|
||||
|
||||
impl AttachmentDescription {
|
||||
/// Returns true if this attachment is compatible with another attachment, as defined in the
|
||||
/// `Render Pass Compatibility` section of the Vulkan specs.
|
||||
#[inline]
|
||||
pub fn is_compatible_with(&self, other: &AttachmentDescription) -> bool {
|
||||
self.format == other.format && self.samples == other.samples
|
||||
}
|
||||
}
|
||||
|
||||
/// Describes one of the subpasses of a render pass.
|
||||
///
|
||||
/// A subpass can use zero or more attachments of various types. Attachment types of which there can
|
||||
@ -847,7 +987,7 @@ impl Default for AttachmentReference {
|
||||
/// the render pass instance began (for `source_subpass`), or on commands that will be submitted
|
||||
/// after the render pass instance ends (for `destination_subpass`). The values must not both be
|
||||
/// `None`.
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub struct SubpassDependency {
|
||||
/// The index of the subpass that writes the data that `destination_subpass` is going to use.
|
||||
///
|
||||
|
Loading…
Reference in New Issue
Block a user