use ash::vk;
use crate::vulkan::owned::{OwnedRenderPass, VkDevice};
pub(super) fn create_main_render_pass(
device: &VkDevice,
format: vk::Format,
msaa: vk::SampleCountFlags,
) -> Result<OwnedRenderPass, String> {
let multisampled = msaa != vk::SampleCountFlags::TYPE_1;
let color_final_layout = if multisampled {
vk::ImageLayout::COLOR_ATTACHMENT_OPTIMAL
} else {
vk::ImageLayout::SHADER_READ_ONLY_OPTIMAL
};
let mut attachments = vec![
vk::AttachmentDescription::default()
.format(format)
.samples(msaa)
.load_op(vk::AttachmentLoadOp::CLEAR)
.store_op(if multisampled {
vk::AttachmentStoreOp::DONT_CARE
} else {
vk::AttachmentStoreOp::STORE
})
.stencil_load_op(vk::AttachmentLoadOp::DONT_CARE)
.stencil_store_op(vk::AttachmentStoreOp::DONT_CARE)
.initial_layout(vk::ImageLayout::UNDEFINED)
.final_layout(color_final_layout),
vk::AttachmentDescription::default()
.format(vk::Format::D32_SFLOAT)
.samples(msaa)
.load_op(vk::AttachmentLoadOp::CLEAR)
.store_op(vk::AttachmentStoreOp::STORE)
.stencil_load_op(vk::AttachmentLoadOp::DONT_CARE)
.stencil_store_op(vk::AttachmentStoreOp::DONT_CARE)
.initial_layout(vk::ImageLayout::UNDEFINED)
.final_layout(vk::ImageLayout::DEPTH_STENCIL_ATTACHMENT_OPTIMAL),
];
if multisampled {
attachments.push(
vk::AttachmentDescription::default()
.format(format)
.samples(vk::SampleCountFlags::TYPE_1)
.load_op(vk::AttachmentLoadOp::DONT_CARE)
.store_op(vk::AttachmentStoreOp::STORE)
.stencil_load_op(vk::AttachmentLoadOp::DONT_CARE)
.stencil_store_op(vk::AttachmentStoreOp::DONT_CARE)
.initial_layout(vk::ImageLayout::UNDEFINED)
.final_layout(vk::ImageLayout::SHADER_READ_ONLY_OPTIMAL),
);
}
let color_ref = vk::AttachmentReference::default()
.attachment(0)
.layout(vk::ImageLayout::COLOR_ATTACHMENT_OPTIMAL);
let depth_ref = vk::AttachmentReference::default()
.attachment(1)
.layout(vk::ImageLayout::DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
let resolve_ref = vk::AttachmentReference::default()
.attachment(2)
.layout(vk::ImageLayout::COLOR_ATTACHMENT_OPTIMAL);
let mut subpass = vk::SubpassDescription::default()
.pipeline_bind_point(vk::PipelineBindPoint::GRAPHICS)
.color_attachments(std::slice::from_ref(&color_ref))
.depth_stencil_attachment(&depth_ref);
if multisampled {
subpass = subpass.resolve_attachments(std::slice::from_ref(&resolve_ref));
}
let dependency = vk::SubpassDependency::default()
.src_subpass(vk::SUBPASS_EXTERNAL)
.dst_subpass(0)
.src_stage_mask(
vk::PipelineStageFlags::COLOR_ATTACHMENT_OUTPUT
| vk::PipelineStageFlags::EARLY_FRAGMENT_TESTS,
)
.src_access_mask(vk::AccessFlags::empty())
.dst_stage_mask(
vk::PipelineStageFlags::COLOR_ATTACHMENT_OUTPUT
| vk::PipelineStageFlags::EARLY_FRAGMENT_TESTS,
)
.dst_access_mask(
vk::AccessFlags::COLOR_ATTACHMENT_WRITE
| vk::AccessFlags::DEPTH_STENCIL_ATTACHMENT_WRITE,
);
let rp_info = vk::RenderPassCreateInfo::default()
.attachments(&attachments)
.subpasses(std::slice::from_ref(&subpass))
.dependencies(std::slice::from_ref(&dependency));
device
.create_render_pass(&rp_info)
.map_err(|e| format!("main render pass: {e}"))
}
pub(super) fn create_main_render_pass_two_pass(
device: &VkDevice,
format: vk::Format,
msaa: vk::SampleCountFlags,
load: bool,
) -> Result<OwnedRenderPass, String> {
let multisampled = msaa != vk::SampleCountFlags::TYPE_1;
let color_final_layout = if multisampled || !load {
vk::ImageLayout::COLOR_ATTACHMENT_OPTIMAL
} else {
vk::ImageLayout::SHADER_READ_ONLY_OPTIMAL
};
let color_load_op = if load {
vk::AttachmentLoadOp::LOAD
} else {
vk::AttachmentLoadOp::CLEAR
};
let color_initial_layout = if load {
vk::ImageLayout::COLOR_ATTACHMENT_OPTIMAL
} else {
vk::ImageLayout::UNDEFINED
};
let depth_load_op = if load {
vk::AttachmentLoadOp::LOAD
} else {
vk::AttachmentLoadOp::CLEAR
};
let depth_initial_layout = if load {
vk::ImageLayout::DEPTH_STENCIL_ATTACHMENT_OPTIMAL
} else {
vk::ImageLayout::UNDEFINED
};
let mut attachments = vec![
vk::AttachmentDescription::default()
.format(format)
.samples(msaa)
.load_op(color_load_op)
.store_op(vk::AttachmentStoreOp::STORE)
.stencil_load_op(vk::AttachmentLoadOp::DONT_CARE)
.stencil_store_op(vk::AttachmentStoreOp::DONT_CARE)
.initial_layout(color_initial_layout)
.final_layout(color_final_layout),
vk::AttachmentDescription::default()
.format(vk::Format::D32_SFLOAT)
.samples(msaa)
.load_op(depth_load_op)
.store_op(vk::AttachmentStoreOp::STORE)
.stencil_load_op(vk::AttachmentLoadOp::DONT_CARE)
.stencil_store_op(vk::AttachmentStoreOp::DONT_CARE)
.initial_layout(depth_initial_layout)
.final_layout(vk::ImageLayout::DEPTH_STENCIL_ATTACHMENT_OPTIMAL),
];
if multisampled {
attachments.push(
vk::AttachmentDescription::default()
.format(format)
.samples(vk::SampleCountFlags::TYPE_1)
.load_op(vk::AttachmentLoadOp::DONT_CARE)
.store_op(vk::AttachmentStoreOp::STORE)
.stencil_load_op(vk::AttachmentLoadOp::DONT_CARE)
.stencil_store_op(vk::AttachmentStoreOp::DONT_CARE)
.initial_layout(vk::ImageLayout::UNDEFINED)
.final_layout(vk::ImageLayout::SHADER_READ_ONLY_OPTIMAL),
);
}
let color_ref = vk::AttachmentReference::default()
.attachment(0)
.layout(vk::ImageLayout::COLOR_ATTACHMENT_OPTIMAL);
let depth_ref = vk::AttachmentReference::default()
.attachment(1)
.layout(vk::ImageLayout::DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
let resolve_ref = vk::AttachmentReference::default()
.attachment(2)
.layout(vk::ImageLayout::COLOR_ATTACHMENT_OPTIMAL);
let mut subpass = vk::SubpassDescription::default()
.pipeline_bind_point(vk::PipelineBindPoint::GRAPHICS)
.color_attachments(std::slice::from_ref(&color_ref))
.depth_stencil_attachment(&depth_ref);
if multisampled {
subpass = subpass.resolve_attachments(std::slice::from_ref(&resolve_ref));
}
let dependency = vk::SubpassDependency::default()
.src_subpass(vk::SUBPASS_EXTERNAL)
.dst_subpass(0)
.src_stage_mask(
vk::PipelineStageFlags::COLOR_ATTACHMENT_OUTPUT
| vk::PipelineStageFlags::EARLY_FRAGMENT_TESTS,
)
.src_access_mask(vk::AccessFlags::empty())
.dst_stage_mask(
vk::PipelineStageFlags::COLOR_ATTACHMENT_OUTPUT
| vk::PipelineStageFlags::EARLY_FRAGMENT_TESTS,
)
.dst_access_mask(
vk::AccessFlags::COLOR_ATTACHMENT_WRITE
| vk::AccessFlags::DEPTH_STENCIL_ATTACHMENT_WRITE,
);
let rp_info = vk::RenderPassCreateInfo::default()
.attachments(&attachments)
.subpasses(std::slice::from_ref(&subpass))
.dependencies(std::slice::from_ref(&dependency));
device
.create_render_pass(&rp_info)
.map_err(|e| format!("two-pass main render pass: {e}"))
}
pub(super) fn create_shadow_render_pass(device: &VkDevice) -> Result<OwnedRenderPass, String> {
let attachment = vk::AttachmentDescription::default()
.format(vk::Format::D32_SFLOAT)
.samples(vk::SampleCountFlags::TYPE_1)
.load_op(vk::AttachmentLoadOp::CLEAR)
.store_op(vk::AttachmentStoreOp::STORE)
.stencil_load_op(vk::AttachmentLoadOp::DONT_CARE)
.stencil_store_op(vk::AttachmentStoreOp::DONT_CARE)
.initial_layout(vk::ImageLayout::DEPTH_STENCIL_ATTACHMENT_OPTIMAL)
.final_layout(vk::ImageLayout::DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
let depth_ref = vk::AttachmentReference::default()
.attachment(0)
.layout(vk::ImageLayout::DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
let subpass = vk::SubpassDescription::default()
.pipeline_bind_point(vk::PipelineBindPoint::GRAPHICS)
.depth_stencil_attachment(&depth_ref);
let rp_info = vk::RenderPassCreateInfo::default()
.attachments(std::slice::from_ref(&attachment))
.subpasses(std::slice::from_ref(&subpass));
device
.create_render_pass(&rp_info)
.map_err(|e| format!("shadow render pass: {e}"))
}
pub(super) fn create_composite_render_pass(
device: &VkDevice,
swapchain_format: vk::Format,
) -> Result<OwnedRenderPass, String> {
let attachment = vk::AttachmentDescription::default()
.format(swapchain_format)
.samples(vk::SampleCountFlags::TYPE_1)
.load_op(vk::AttachmentLoadOp::DONT_CARE)
.store_op(vk::AttachmentStoreOp::STORE)
.stencil_load_op(vk::AttachmentLoadOp::DONT_CARE)
.stencil_store_op(vk::AttachmentStoreOp::DONT_CARE)
.initial_layout(vk::ImageLayout::UNDEFINED)
.final_layout(vk::ImageLayout::PRESENT_SRC_KHR);
let color_ref = vk::AttachmentReference::default()
.attachment(0)
.layout(vk::ImageLayout::COLOR_ATTACHMENT_OPTIMAL);
let subpass = vk::SubpassDescription::default()
.pipeline_bind_point(vk::PipelineBindPoint::GRAPHICS)
.color_attachments(std::slice::from_ref(&color_ref));
let dependency = vk::SubpassDependency::default()
.src_subpass(vk::SUBPASS_EXTERNAL)
.dst_subpass(0)
.src_stage_mask(vk::PipelineStageFlags::COLOR_ATTACHMENT_OUTPUT)
.src_access_mask(vk::AccessFlags::COLOR_ATTACHMENT_WRITE)
.dst_stage_mask(
vk::PipelineStageFlags::COLOR_ATTACHMENT_OUTPUT
| vk::PipelineStageFlags::FRAGMENT_SHADER,
)
.dst_access_mask(vk::AccessFlags::COLOR_ATTACHMENT_WRITE | vk::AccessFlags::SHADER_READ);
let rp_info = vk::RenderPassCreateInfo::default()
.attachments(std::slice::from_ref(&attachment))
.subpasses(std::slice::from_ref(&subpass))
.dependencies(std::slice::from_ref(&dependency));
device
.create_render_pass(&rp_info)
.map_err(|e| format!("composite render pass: {e}"))
}
pub(super) fn create_bloom_render_pass(
device: &VkDevice,
format: vk::Format,
load: bool,
) -> Result<OwnedRenderPass, String> {
let attachment = vk::AttachmentDescription::default()
.format(format)
.samples(vk::SampleCountFlags::TYPE_1)
.load_op(if load {
vk::AttachmentLoadOp::LOAD
} else {
vk::AttachmentLoadOp::DONT_CARE
})
.store_op(vk::AttachmentStoreOp::STORE)
.stencil_load_op(vk::AttachmentLoadOp::DONT_CARE)
.stencil_store_op(vk::AttachmentStoreOp::DONT_CARE)
.initial_layout(if load {
vk::ImageLayout::SHADER_READ_ONLY_OPTIMAL
} else {
vk::ImageLayout::UNDEFINED
})
.final_layout(vk::ImageLayout::SHADER_READ_ONLY_OPTIMAL);
let color_ref = vk::AttachmentReference::default()
.attachment(0)
.layout(vk::ImageLayout::COLOR_ATTACHMENT_OPTIMAL);
let subpass = vk::SubpassDescription::default()
.pipeline_bind_point(vk::PipelineBindPoint::GRAPHICS)
.color_attachments(std::slice::from_ref(&color_ref));
let dependency = vk::SubpassDependency::default()
.src_subpass(vk::SUBPASS_EXTERNAL)
.dst_subpass(0)
.src_stage_mask(vk::PipelineStageFlags::COLOR_ATTACHMENT_OUTPUT)
.src_access_mask(vk::AccessFlags::COLOR_ATTACHMENT_WRITE)
.dst_stage_mask(
vk::PipelineStageFlags::COLOR_ATTACHMENT_OUTPUT
| vk::PipelineStageFlags::FRAGMENT_SHADER,
)
.dst_access_mask(
vk::AccessFlags::COLOR_ATTACHMENT_WRITE
| vk::AccessFlags::COLOR_ATTACHMENT_READ
| vk::AccessFlags::SHADER_READ,
);
let rp_info = vk::RenderPassCreateInfo::default()
.attachments(std::slice::from_ref(&attachment))
.subpasses(std::slice::from_ref(&subpass))
.dependencies(std::slice::from_ref(&dependency));
device
.create_render_pass(&rp_info)
.map_err(|e| format!("bloom render pass: {e}"))
}