Add option to reuse renderpass in rendertarget

This commit is contained in:
hodasemi 2023-01-21 11:11:48 +01:00
parent dca9ab20be
commit 358c3c5182
5 changed files with 217 additions and 246 deletions

View file

@ -9,6 +9,7 @@ pub mod sub_pass;
use sub_pass::{AttachmentInfo, AttachmentInfoUsage, SubPass}; use sub_pass::{AttachmentInfo, AttachmentInfoUsage, SubPass};
pub struct RenderTargetBuilder { pub struct RenderTargetBuilder {
old_render_target: Option<RenderTarget>,
sub_passes: Vec<SubPass>, sub_passes: Vec<SubPass>,
} }
@ -19,6 +20,12 @@ impl RenderTargetBuilder {
self self
} }
pub fn preserve_old_render_pass(mut self, render_target: RenderTarget) -> Self {
self.old_render_target = Some(render_target);
self
}
pub fn build(self, device: &Arc<Device>) -> Result<RenderTarget> { pub fn build(self, device: &Arc<Device>) -> Result<RenderTarget> {
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
{ {
@ -33,8 +40,24 @@ impl RenderTargetBuilder {
} }
} }
// create render pass let mut clear_values = Vec::new();
self.map_attachment(|attachment| {
clear_values.push(attachment.clear_value.clone());
});
// create render pass
let render_pass = match self.old_render_target {
Some(old_render_target) => {
if !Self::verify_setups(&old_render_target.sub_passes, &self.sub_passes) {
return Err(anyhow::anyhow!(
"Can't preserve old RenderPass if subpasses don't match!"
));
}
old_render_target.render_pass
}
None => {
// gather attachment descriptions // gather attachment descriptions
let mut attachments = Vec::new(); let mut attachments = Vec::new();
@ -82,7 +105,8 @@ impl RenderTargetBuilder {
if let Some(input_info) = sub_pass.inputs() { if let Some(input_info) = sub_pass.inputs() {
debug_assert!(input_info.sub_pass_index < attachment_references.len()); debug_assert!(input_info.sub_pass_index < attachment_references.len());
let input_pass_references = &attachment_references[input_info.sub_pass_index]; let input_pass_references =
&attachment_references[input_info.sub_pass_index];
for input_index in input_info.input_indices.iter() { for input_index in input_info.input_indices.iter() {
references.input_attachments.push(VkAttachmentReference { references.input_attachments.push(VkAttachmentReference {
@ -140,53 +164,19 @@ impl RenderTargetBuilder {
last_dependency.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT.into(); last_dependency.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT.into();
} }
// dependencies.push(VkSubpassDependency::new( RenderPass::new(device.clone(), &descriptions, &attachments, &dependencies)?
// self.sub_passes.len() as u32 - 1, }
// VK_SUBPASS_EXTERNAL, };
// VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
// VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
// VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
// VK_ACCESS_MEMORY_READ_BIT,
// VK_DEPENDENCY_BY_REGION_BIT,
// ));
let render_pass =
RenderPass::new(device.clone(), &descriptions, &attachments, &dependencies)?;
// create frame buffers // create frame buffers
let max_images = self.max_images(); let framebuffers = Self::create_framebuffers(&render_pass, &self.sub_passes)?;
let extent = self.sub_passes[0].extent();
let framebuffers: Result<Vec<Arc<Framebuffer>>> = (0..max_images)
.map(|i| {
let mut framebuffer_builder = Framebuffer::builder()
.set_render_pass(&render_pass)
.set_width(extent.width)
.set_height(extent.height);
for sub_pass in self.sub_passes.iter() {
for attachment in sub_pass.attachments().iter() {
framebuffer_builder =
framebuffer_builder.add_attachment(attachment.image(i));
}
}
framebuffer_builder.build(render_pass.device().clone())
})
.collect();
let mut clear_values = Vec::new();
self.map_attachment(|attachment| {
clear_values.push(attachment.clear_value.clone());
});
Ok(RenderTarget { Ok(RenderTarget {
render_pass, render_pass,
framebuffers: framebuffers?, framebuffers,
clear_values, clear_values,
extent, extent: self.sub_passes[0].extent(),
sub_passes: self.sub_passes, sub_passes: self.sub_passes,
@ -195,17 +185,56 @@ impl RenderTargetBuilder {
}) })
} }
fn create_framebuffers(
render_pass: &Arc<RenderPass>,
sub_passes: &[SubPass],
) -> Result<Vec<Arc<Framebuffer>>> {
let extent = sub_passes[0].extent();
(0..Self::max_images(sub_passes))
.map(|i| {
let mut framebuffer_builder = Framebuffer::builder()
.set_render_pass(render_pass)
.set_width(extent.width)
.set_height(extent.height);
for sub_pass in sub_passes.iter() {
for attachment in sub_pass.attachments().iter() {
framebuffer_builder =
framebuffer_builder.add_attachment(attachment.image(i));
}
}
framebuffer_builder.build(render_pass.device().clone())
})
.collect()
}
#[inline] #[inline]
fn max_images(&self) -> usize { fn max_images(sub_passes: &[SubPass]) -> usize {
let mut max_images = 0; let mut max_images = 0;
for sub_pass in self.sub_passes.iter() { for sub_pass in sub_passes.iter() {
max_images = max_images.max(sub_pass.max_images_per_attachment()); max_images = max_images.max(sub_pass.max_images_per_attachment());
} }
max_images max_images
} }
fn verify_setups(old_sub_passes: &[SubPass], new_sub_passes: &[SubPass]) -> bool {
if old_sub_passes.len() != new_sub_passes.len() {
return false;
}
for (new_sub_pass, old_sub_pass) in old_sub_passes.iter().zip(new_sub_passes.iter()) {
if !new_sub_pass.verify_setup(old_sub_pass) {
return false;
}
}
true
}
#[inline] #[inline]
fn map_attachment<'a, F>(&'a self, mut f: F) fn map_attachment<'a, F>(&'a self, mut f: F)
where where
@ -247,6 +276,7 @@ pub struct RenderTarget {
impl RenderTarget { impl RenderTarget {
pub fn builder() -> RenderTargetBuilder { pub fn builder() -> RenderTargetBuilder {
RenderTargetBuilder { RenderTargetBuilder {
old_render_target: None,
sub_passes: Vec::new(), sub_passes: Vec::new(),
} }
} }
@ -315,99 +345,3 @@ impl RenderTarget {
buffer_recorder.end_render_pass(); buffer_recorder.end_render_pass();
} }
} }
// impl<'a> RenderTargetBuilder<'a> {
// fn create_images_and_renderpass(&self, device: &Arc<Device>) -> Result<Arc<RenderPass>> {
// let subpass_descriptions = [match resolve_reference {
// Some(resvole_ref) => VkSubpassDescription::new(
// 0,
// &[],
// color_references.as_slice(),
// &[resvole_ref],
// match depth_reference {
// Some(ref depth_ref) => Some(depth_ref),
// None => None,
// },
// &[],
// ),
// None => VkSubpassDescription::new(
// 0,
// &[],
// color_references.as_slice(),
// &[],
// match depth_reference {
// Some(ref depth_ref) => Some(depth_ref),
// None => None,
// },
// &[],
// ),
// }];
// let dependencies = if color_references.is_empty() {
// // assume, that when no color references are given,
// // we want to store the depth information for later
// if depth_reference.is_some() {
// for attachment in &mut attachments {
// if attachment.format == VK_FORMAT_D16_UNORM {
// attachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
// attachment.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL;
// break;
// }
// }
// }
// [
// VkSubpassDependency::new(
// VK_SUBPASS_EXTERNAL,
// 0,
// VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
// VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
// 0,
// VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT
// | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
// VK_DEPENDENCY_BY_REGION_BIT,
// ),
// VkSubpassDependency::new(
// 0,
// VK_SUBPASS_EXTERNAL,
// VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
// VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
// VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT
// | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
// VK_ACCESS_SHADER_READ_BIT,
// VK_DEPENDENCY_BY_REGION_BIT,
// ),
// ]
// } else {
// [
// VkSubpassDependency::new(
// VK_SUBPASS_EXTERNAL,
// 0,
// VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
// VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
// VK_ACCESS_MEMORY_READ_BIT,
// VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
// VK_DEPENDENCY_BY_REGION_BIT,
// ),
// VkSubpassDependency::new(
// 0,
// VK_SUBPASS_EXTERNAL,
// VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
// VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
// VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
// VK_ACCESS_MEMORY_READ_BIT,
// VK_DEPENDENCY_BY_REGION_BIT,
// ),
// ]
// };
// let renderpass = RenderPass::new(
// device.clone(),
// &subpass_descriptions,
// attachments.as_slice(),
// &dependencies,
// )?;
// Ok(renderpass)
// }
// }

View file

@ -157,7 +157,7 @@ impl<'a> From<&'a Vec<Arc<Image>>> for ResolveTarget {
} }
} }
#[derive(Debug)] #[derive(Debug, PartialEq, Eq)]
pub struct InputAttachmentInfo { pub struct InputAttachmentInfo {
pub sub_pass_index: usize, pub sub_pass_index: usize,
pub input_indices: Vec<usize>, pub input_indices: Vec<usize>,
@ -383,6 +383,13 @@ impl AttachmentInfo {
&self.images[index] &self.images[index]
} }
fn verify_setup(&self, other: &Self) -> bool {
self.clear_value == other.clear_value
&& self.layout == other.layout
&& self.description == other.description
&& self.usage == other.usage
}
} }
#[derive(Debug)] #[derive(Debug)]
@ -439,4 +446,34 @@ impl SubPass {
max_images max_images
} }
pub(crate) fn verify_setup(&self, other: &Self) -> bool {
if self.output_usage != other.output_usage {
return false;
}
match (&self.input_info, &other.input_info) {
(None, None) => (),
(Some(self_input_info), Some(other_input_info)) => {
if self_input_info != other_input_info {
return false;
}
}
(None, Some(_)) | (Some(_), None) => return false,
}
if self.attachments.len() != other.attachments.len() {
return false;
}
for (self_attachment, other_attachment) in
self.attachments.iter().zip(other.attachments.iter())
{
if !self_attachment.verify_setup(other_attachment) {
return false;
}
}
true
}
} }

View file

@ -1,7 +1,7 @@
use crate::prelude::*; use crate::prelude::*;
#[repr(C)] #[repr(C)]
#[derive(Debug, Clone)] #[derive(Debug, Clone, PartialEq, Eq)]
pub struct VkAttachmentDescription { pub struct VkAttachmentDescription {
pub flags: VkAttachmentDescriptionFlagBits, pub flags: VkAttachmentDescriptionFlagBits,
pub format: VkFormat, pub format: VkFormat,

View file

@ -1,7 +1,7 @@
use std::mem; use std::mem;
#[repr(C)] #[repr(C)]
#[derive(Debug, Clone)] #[derive(Debug, Clone, PartialEq, Eq)]
pub struct VkClearColorValue([u32; 4]); pub struct VkClearColorValue([u32; 4]);
impl VkClearColorValue { impl VkClearColorValue {

View file

@ -3,7 +3,7 @@ use crate::prelude::*;
use std::mem; use std::mem;
#[repr(C)] #[repr(C)]
#[derive(Debug, Clone)] #[derive(Debug, Clone, PartialEq, Eq)]
pub struct VkClearValue(VkClearColorValue); pub struct VkClearValue(VkClearColorValue);
impl VkClearValue { impl VkClearValue {