aboutsummaryrefslogtreecommitdiff
path: root/adapters/fparkan-render-vulkan/src/ffi/swapchain_resources.rs
diff options
context:
space:
mode:
Diffstat (limited to 'adapters/fparkan-render-vulkan/src/ffi/swapchain_resources.rs')
-rw-r--r--adapters/fparkan-render-vulkan/src/ffi/swapchain_resources.rs85
1 files changed, 71 insertions, 14 deletions
diff --git a/adapters/fparkan-render-vulkan/src/ffi/swapchain_resources.rs b/adapters/fparkan-render-vulkan/src/ffi/swapchain_resources.rs
index 07c2869..ff797e1 100644
--- a/adapters/fparkan-render-vulkan/src/ffi/swapchain_resources.rs
+++ b/adapters/fparkan-render-vulkan/src/ffi/swapchain_resources.rs
@@ -1,19 +1,22 @@
#![allow(unsafe_code)]
use ash::vk;
+use fparkan_platform::DepthStencilSupport;
use fparkan_render::{
LegacyBlendMode, LegacyCullMode, LegacyDepthMode, LegacyPipelineState, PipelineKey,
};
use std::collections::BTreeMap;
use super::{
- color_subresource_range, VulkanAllocatedBuffer, VulkanAllocatedImage, VulkanLogicalDeviceProbe,
- VulkanSmokeRendererError, VulkanSwapchainProbe, TRIANGLE_FRAGMENT_SHADER_WORDS,
- TRIANGLE_VERTEX_SHADER_WORDS,
+ color_subresource_range, create_depth_attachment, destroy_depth_attachment,
+ VulkanAllocatedBuffer, VulkanAllocatedImage, VulkanDepthAttachment, VulkanInstanceProbe,
+ VulkanLogicalDeviceProbe, VulkanSmokeRendererError, VulkanSwapchainProbe,
+ TRIANGLE_FRAGMENT_SHADER_WORDS, TRIANGLE_VERTEX_SHADER_WORDS,
};
pub(super) struct VulkanSwapchainResources {
pub(super) image_views: Vec<vk::ImageView>,
+ pub(super) depth_attachment: VulkanDepthAttachment,
pub(super) render_pass: vk::RenderPass,
pub(super) pipeline_layout: vk::PipelineLayout,
pub(super) descriptor_set_layout: vk::DescriptorSetLayout,
@@ -28,6 +31,7 @@ pub(super) struct VulkanSwapchainResources {
struct PartialSwapchainResources {
image_views: Vec<vk::ImageView>,
+ depth_attachment: Option<VulkanDepthAttachment>,
render_pass: Option<vk::RenderPass>,
pipeline_layout: Option<vk::PipelineLayout>,
descriptor_set_layout: Option<vk::DescriptorSetLayout>,
@@ -38,8 +42,9 @@ struct PartialSwapchainResources {
command_buffers: Vec<vk::CommandBuffer>,
}
-#[allow(clippy::too_many_arguments)]
+#[allow(clippy::too_many_arguments, clippy::too_many_lines)]
pub(super) fn create_swapchain_resources(
+ instance: &VulkanInstanceProbe,
device: &VulkanLogicalDeviceProbe,
swapchain: &VulkanSwapchainProbe,
command_pool: vk::CommandPool,
@@ -47,6 +52,7 @@ pub(super) fn create_swapchain_resources(
index_buffer: &VulkanAllocatedBuffer,
textures: &[VulkanAllocatedImage],
draw_ranges: &[super::VulkanStaticDrawRange],
+ depth_request: DepthStencilSupport,
reuse_command_pool: bool,
) -> Result<VulkanSwapchainResources, VulkanSmokeRendererError> {
// SAFETY: The swapchain is live and owned by this renderer for the duration of the query.
@@ -65,6 +71,7 @@ pub(super) fn create_swapchain_resources(
&images,
swapchain.report.plan.format.format,
)?,
+ depth_attachment: None,
render_pass: None,
pipeline_layout: None,
descriptor_set_layout: None,
@@ -75,6 +82,7 @@ pub(super) fn create_swapchain_resources(
command_buffers: Vec::new(),
};
let (
+ depth_attachment,
render_pass,
pipeline_layout,
pipelines,
@@ -83,11 +91,13 @@ pub(super) fn create_swapchain_resources(
descriptor_sets,
sampler,
) = match create_swapchain_pipeline_bundle(
+ instance,
device,
swapchain.report.plan.format.format,
swapchain.report.plan.extent,
textures,
draw_ranges,
+ depth_request,
) {
Ok(bundle) => bundle,
Err(error) => {
@@ -95,6 +105,8 @@ pub(super) fn create_swapchain_resources(
return Err(error);
}
};
+ let depth_view = depth_attachment.image.view;
+ partial.depth_attachment = Some(depth_attachment);
partial.render_pass = Some(render_pass);
partial.pipeline_layout = Some(pipeline_layout);
partial.descriptor_set_layout = Some(descriptor_set_layout);
@@ -105,6 +117,7 @@ pub(super) fn create_swapchain_resources(
device,
render_pass,
&partial.image_views,
+ depth_view,
swapchain.report.plan.extent,
) {
Ok(framebuffers) => framebuffers,
@@ -128,8 +141,16 @@ pub(super) fn create_swapchain_resources(
};
partial.command_buffers = command_buffers;
let _ = (vertex_buffer, index_buffer);
+ let depth_attachment =
+ partial
+ .depth_attachment
+ .take()
+ .ok_or(VulkanSmokeRendererError::InvariantViolation {
+ context: "depth attachment ownership after swapchain setup",
+ })?;
Ok(VulkanSwapchainResources {
image_views: partial.image_views,
+ depth_attachment,
render_pass,
pipeline_layout,
descriptor_set_layout,
@@ -156,13 +177,16 @@ fn create_swapchain_image_views(
#[allow(clippy::type_complexity)]
fn create_swapchain_pipeline_bundle(
+ instance: &VulkanInstanceProbe,
device: &VulkanLogicalDeviceProbe,
format: i32,
extent: (u32, u32),
textures: &[VulkanAllocatedImage],
draw_ranges: &[super::VulkanStaticDrawRange],
+ depth_request: DepthStencilSupport,
) -> Result<
(
+ VulkanDepthAttachment,
vk::RenderPass,
vk::PipelineLayout,
BTreeMap<PipelineKey, vk::Pipeline>,
@@ -173,11 +197,19 @@ fn create_swapchain_pipeline_bundle(
),
VulkanSmokeRendererError,
> {
- let render_pass = create_render_pass(device, format)?;
+ let depth_attachment = create_depth_attachment(instance, device, extent, depth_request)?;
+ let render_pass = match create_render_pass(device, format, depth_attachment.format) {
+ Ok(render_pass) => render_pass,
+ Err(error) => {
+ destroy_depth_attachment(device, &depth_attachment);
+ return Err(error);
+ }
+ };
let (descriptor_set_layout, descriptor_pool, descriptor_sets, sampler) =
create_texture_descriptor_bundle(device, textures).inspect_err(|_| {
// SAFETY: The render pass was created above on this live logical device and is destroyed on setup failure.
unsafe { device.device().destroy_render_pass(render_pass, None) };
+ destroy_depth_attachment(device, &depth_attachment);
})?;
let pipeline_layout =
create_pipeline_layout(device, descriptor_set_layout).inspect_err(|_| {
@@ -192,6 +224,7 @@ fn create_swapchain_pipeline_bundle(
.destroy_descriptor_set_layout(descriptor_set_layout, None);
device.device().destroy_render_pass(render_pass, None);
}
+ destroy_depth_attachment(device, &depth_attachment);
})?;
let pipelines =
create_graphics_pipeline_cache(device, render_pass, pipeline_layout, extent, draw_ranges)
@@ -210,8 +243,10 @@ fn create_swapchain_pipeline_bundle(
.destroy_descriptor_set_layout(descriptor_set_layout, None);
device.device().destroy_render_pass(render_pass, None);
}
+ destroy_depth_attachment(device, &depth_attachment);
})?;
Ok((
+ depth_attachment,
render_pass,
pipeline_layout,
pipelines,
@@ -226,11 +261,12 @@ fn create_swapchain_framebuffers(
device: &VulkanLogicalDeviceProbe,
render_pass: vk::RenderPass,
image_views: &[vk::ImageView],
+ depth_view: vk::ImageView,
extent: (u32, u32),
) -> Result<Vec<vk::Framebuffer>, VulkanSmokeRendererError> {
let mut framebuffers = Vec::with_capacity(image_views.len());
for image_view in image_views.iter().copied() {
- match create_framebuffer(device, render_pass, image_view, extent) {
+ match create_framebuffer(device, render_pass, image_view, depth_view, extent) {
Ok(framebuffer) => framebuffers.push(framebuffer),
Err(error) => {
// SAFETY: These framebuffers were created above on this live logical device and are destroyed on setup failure.
@@ -288,6 +324,7 @@ fn create_image_view(
fn create_render_pass(
device: &VulkanLogicalDeviceProbe,
format: i32,
+ depth_format: vk::Format,
) -> Result<vk::RenderPass, VulkanSmokeRendererError> {
let color_attachment = vk::AttachmentDescription::default()
.format(vk::Format::from_raw(format))
@@ -299,10 +336,23 @@ fn create_render_pass(
let color_attachment_ref = vk::AttachmentReference::default()
.attachment(0)
.layout(vk::ImageLayout::COLOR_ATTACHMENT_OPTIMAL);
+ let depth_attachment = vk::AttachmentDescription::default()
+ .format(depth_format)
+ .samples(vk::SampleCountFlags::TYPE_1)
+ .load_op(vk::AttachmentLoadOp::CLEAR)
+ .store_op(vk::AttachmentStoreOp::DONT_CARE)
+ .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);
+ let depth_attachment_ref = vk::AttachmentReference::default()
+ .attachment(1)
+ .layout(vk::ImageLayout::DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
let color_attachments = [color_attachment_ref];
let subpass = vk::SubpassDescription::default()
.pipeline_bind_point(vk::PipelineBindPoint::GRAPHICS)
- .color_attachments(&color_attachments);
+ .color_attachments(&color_attachments)
+ .depth_stencil_attachment(&depth_attachment_ref);
let dependency = vk::SubpassDependency::default()
.src_subpass(vk::SUBPASS_EXTERNAL)
.dst_subpass(0)
@@ -310,7 +360,7 @@ fn create_render_pass(
.dst_stage_mask(vk::PipelineStageFlags::COLOR_ATTACHMENT_OUTPUT)
.src_access_mask(vk::AccessFlags::empty())
.dst_access_mask(vk::AccessFlags::COLOR_ATTACHMENT_WRITE);
- let attachments = [color_attachment];
+ let attachments = [color_attachment, depth_attachment];
let subpasses = [subpass];
let dependencies = [dependency];
let create_info = vk::RenderPassCreateInfo::default()
@@ -512,11 +562,6 @@ fn create_graphics_pipeline(
extent: (u32, u32),
state: LegacyPipelineState,
) -> Result<vk::Pipeline, VulkanSmokeRendererError> {
- if state.depth != LegacyDepthMode::Disabled {
- return Err(VulkanSmokeRendererError::InvalidStaticMesh {
- context: "static renderer has no depth attachment for requested pipeline state",
- });
- }
if state.alpha_test {
return Err(VulkanSmokeRendererError::InvalidStaticMesh {
context:
@@ -604,6 +649,12 @@ fn create_graphics_pipeline(
let multisample_state = vk::PipelineMultisampleStateCreateInfo::default()
.sample_shading_enable(false)
.rasterization_samples(vk::SampleCountFlags::TYPE_1);
+ let depth_stencil_state = vk::PipelineDepthStencilStateCreateInfo::default()
+ .depth_test_enable(state.depth != LegacyDepthMode::Disabled)
+ .depth_write_enable(state.depth == LegacyDepthMode::TestWrite)
+ .depth_compare_op(vk::CompareOp::LESS_OR_EQUAL)
+ .depth_bounds_test_enable(false)
+ .stencil_test_enable(false);
let color_blend_attachment = vk::PipelineColorBlendAttachmentState::default()
.color_write_mask(
vk::ColorComponentFlags::R
@@ -629,6 +680,7 @@ fn create_graphics_pipeline(
.viewport_state(&viewport_state)
.rasterization_state(&rasterization_state)
.multisample_state(&multisample_state)
+ .depth_stencil_state(&depth_stencil_state)
.color_blend_state(&color_blend_state)
.layout(pipeline_layout)
.render_pass(render_pass)
@@ -671,9 +723,10 @@ fn create_framebuffer(
device: &VulkanLogicalDeviceProbe,
render_pass: vk::RenderPass,
image_view: vk::ImageView,
+ depth_view: vk::ImageView,
extent: (u32, u32),
) -> Result<vk::Framebuffer, VulkanSmokeRendererError> {
- let attachments = [image_view];
+ let attachments = [image_view, depth_view];
let create_info = vk::FramebufferCreateInfo::default()
.render_pass(render_pass)
.attachments(&attachments)
@@ -738,6 +791,7 @@ pub(super) fn destroy_swapchain_resources(
device
.device()
.destroy_render_pass(resources.render_pass, None);
+ destroy_depth_attachment(device, &resources.depth_attachment);
for image_view in resources.image_views {
device.device().destroy_image_view(image_view, None);
}
@@ -783,6 +837,9 @@ fn destroy_partial_swapchain_resources(
if let Some(render_pass) = partial.render_pass {
device.device().destroy_render_pass(render_pass, None);
}
+ if let Some(depth_attachment) = partial.depth_attachment {
+ destroy_depth_attachment(device, &depth_attachment);
+ }
for image_view in partial.image_views {
device.device().destroy_image_view(image_view, None);
}