2022-12-22 13:39:31 +11:00
|
|
|
use crate::{error, util};
|
2022-12-10 17:25:36 +11:00
|
|
|
use ash::vk;
|
2023-01-13 17:48:04 +11:00
|
|
|
|
2023-02-13 14:36:50 +11:00
|
|
|
use crate::error::FilterChainError;
|
2023-02-08 15:08:44 +11:00
|
|
|
use crate::framebuffer::OutputImage;
|
2023-01-29 18:30:58 +11:00
|
|
|
use crate::render_pass::VulkanRenderPass;
|
2023-02-17 09:33:47 +11:00
|
|
|
use ash::vk::PushConstantRange;
|
2024-02-22 16:41:29 +11:00
|
|
|
use bytemuck::offset_of;
|
2023-02-16 09:40:24 +11:00
|
|
|
use librashader_cache::cache_pipeline;
|
2024-09-12 13:44:33 +10:00
|
|
|
use librashader_common::map::FastHashMap;
|
2022-12-10 17:25:36 +11:00
|
|
|
use librashader_reflect::back::ShaderCompilerOutput;
|
2024-02-06 17:32:08 +11:00
|
|
|
use librashader_reflect::reflect::semantics::{BufferReflection, TextureBinding};
|
2022-12-10 17:25:36 +11:00
|
|
|
use librashader_reflect::reflect::ShaderReflection;
|
2024-02-22 16:41:29 +11:00
|
|
|
use librashader_runtime::quad::VertexInput;
|
2023-02-08 15:08:44 +11:00
|
|
|
use librashader_runtime::render_target::RenderTarget;
|
2022-12-22 13:39:31 +11:00
|
|
|
use std::ffi::CStr;
|
2023-02-09 13:21:40 +11:00
|
|
|
use std::sync::Arc;
|
2024-09-12 13:44:33 +10:00
|
|
|
|
2023-01-16 03:08:13 +11:00
|
|
|
const ENTRY_POINT: &CStr = unsafe { CStr::from_bytes_with_nul_unchecked(b"main\0") };
|
2023-01-13 16:07:03 +11:00
|
|
|
|
2024-08-01 15:23:18 +10:00
|
|
|
pub struct PipelineDescriptors<'a> {
|
2022-12-10 17:25:36 +11:00
|
|
|
pub replicas: u32,
|
2024-08-01 15:23:18 +10:00
|
|
|
pub layout_bindings: Vec<vk::DescriptorSetLayoutBinding<'a>>,
|
2022-12-22 13:39:31 +11:00
|
|
|
pub pool_sizes: Vec<vk::DescriptorPoolSize>,
|
2022-12-10 17:25:36 +11:00
|
|
|
}
|
|
|
|
|
2024-08-01 15:23:18 +10:00
|
|
|
impl PipelineDescriptors<'_> {
|
2022-12-10 17:25:36 +11:00
|
|
|
pub fn new(duplicates: u32) -> Self {
|
|
|
|
Self {
|
|
|
|
replicas: duplicates,
|
|
|
|
layout_bindings: vec![],
|
|
|
|
pool_sizes: vec![],
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-12-14 11:24:00 +11:00
|
|
|
pub fn add_ubo_binding(&mut self, ubo_meta: Option<&BufferReflection<u32>>) {
|
2024-09-14 08:06:04 +10:00
|
|
|
if let Some(ubo_meta) = ubo_meta.filter(|ubo_meta| !ubo_meta.stage_mask.is_empty()) {
|
2023-01-12 10:04:35 +11:00
|
|
|
let ubo_mask = util::binding_stage_to_vulkan_stage(ubo_meta.stage_mask);
|
2022-12-10 17:25:36 +11:00
|
|
|
|
|
|
|
self.layout_bindings.push(vk::DescriptorSetLayoutBinding {
|
|
|
|
binding: ubo_meta.binding,
|
|
|
|
descriptor_type: vk::DescriptorType::UNIFORM_BUFFER,
|
|
|
|
descriptor_count: 1,
|
|
|
|
stage_flags: ubo_mask,
|
|
|
|
p_immutable_samplers: std::ptr::null(),
|
2024-08-01 15:23:18 +10:00
|
|
|
_marker: Default::default(),
|
2022-12-10 17:25:36 +11:00
|
|
|
});
|
|
|
|
|
|
|
|
self.pool_sizes.push(vk::DescriptorPoolSize {
|
|
|
|
ty: vk::DescriptorType::UNIFORM_BUFFER,
|
|
|
|
descriptor_count: self.replicas,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn add_texture_bindings<'a>(&mut self, textures: impl Iterator<Item = &'a TextureBinding>) {
|
2023-01-12 10:04:35 +11:00
|
|
|
let texture_mask = vk::ShaderStageFlags::FRAGMENT;
|
2022-12-10 17:25:36 +11:00
|
|
|
for texture in textures {
|
|
|
|
self.layout_bindings.push(vk::DescriptorSetLayoutBinding {
|
|
|
|
binding: texture.binding,
|
|
|
|
descriptor_type: vk::DescriptorType::COMBINED_IMAGE_SAMPLER,
|
|
|
|
descriptor_count: 1,
|
|
|
|
stage_flags: texture_mask,
|
|
|
|
p_immutable_samplers: std::ptr::null(),
|
2024-08-01 15:23:18 +10:00
|
|
|
_marker: Default::default(),
|
2022-12-10 17:25:36 +11:00
|
|
|
});
|
|
|
|
|
|
|
|
self.pool_sizes.push(vk::DescriptorPoolSize {
|
|
|
|
ty: vk::DescriptorType::COMBINED_IMAGE_SAMPLER,
|
|
|
|
descriptor_count: self.replicas,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn bindings(&self) -> &[vk::DescriptorSetLayoutBinding] {
|
|
|
|
self.layout_bindings.as_ref()
|
|
|
|
}
|
|
|
|
|
2022-12-22 13:39:31 +11:00
|
|
|
pub fn create_descriptor_set_layout(
|
|
|
|
&self,
|
|
|
|
device: &ash::Device,
|
|
|
|
) -> error::Result<vk::DescriptorSetLayout> {
|
2022-12-10 17:25:36 +11:00
|
|
|
unsafe {
|
|
|
|
let layout = device.create_descriptor_set_layout(
|
2024-08-01 15:23:18 +10:00
|
|
|
&vk::DescriptorSetLayoutCreateInfo::default().bindings(self.bindings()),
|
2022-12-22 13:39:31 +11:00
|
|
|
None,
|
|
|
|
)?;
|
2022-12-10 17:25:36 +11:00
|
|
|
Ok(layout)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub struct PipelineLayoutObjects {
|
|
|
|
pub layout: vk::PipelineLayout,
|
|
|
|
pub descriptor_sets: Vec<vk::DescriptorSet>,
|
2024-09-12 13:44:33 +10:00
|
|
|
pub descriptor_sets_alt: Vec<vk::DescriptorSet>,
|
|
|
|
|
2024-08-01 15:23:18 +10:00
|
|
|
pub _pool: vk::DescriptorPool,
|
|
|
|
pub _descriptor_set_layout: [vk::DescriptorSetLayout; 1],
|
2022-12-10 17:25:36 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
impl PipelineLayoutObjects {
|
2022-12-22 13:39:31 +11:00
|
|
|
pub fn new(
|
|
|
|
reflection: &ShaderReflection,
|
|
|
|
replicas: u32,
|
|
|
|
device: &ash::Device,
|
|
|
|
) -> error::Result<Self> {
|
2022-12-10 17:25:36 +11:00
|
|
|
let mut descriptors = PipelineDescriptors::new(replicas);
|
|
|
|
descriptors.add_ubo_binding(reflection.ubo.as_ref());
|
|
|
|
descriptors.add_texture_bindings(reflection.meta.texture_meta.values());
|
|
|
|
|
2023-01-13 17:48:04 +11:00
|
|
|
let descriptor_set_layout = [descriptors.create_descriptor_set_layout(device)?];
|
2022-12-10 17:25:36 +11:00
|
|
|
|
2023-01-12 10:04:35 +11:00
|
|
|
let pipeline_create_info =
|
2024-08-01 15:23:18 +10:00
|
|
|
vk::PipelineLayoutCreateInfo::default().set_layouts(&descriptor_set_layout);
|
2022-12-10 17:25:36 +11:00
|
|
|
|
2023-02-17 09:33:47 +11:00
|
|
|
let push_constant_range = reflection.push_constant.as_ref().map(|push_constant| {
|
|
|
|
let stage_mask = util::binding_stage_to_vulkan_stage(push_constant.stage_mask);
|
2024-08-01 15:23:18 +10:00
|
|
|
[vk::PushConstantRange::default()
|
2023-02-17 09:33:47 +11:00
|
|
|
.stage_flags(stage_mask)
|
|
|
|
.size(push_constant.size)]
|
|
|
|
});
|
2023-02-16 14:57:20 +11:00
|
|
|
|
2023-02-17 09:33:47 +11:00
|
|
|
let push_constant_range: &[PushConstantRange] =
|
|
|
|
push_constant_range.as_ref().map_or(&[], |o| o);
|
2023-02-16 14:57:20 +11:00
|
|
|
|
2023-02-17 09:33:47 +11:00
|
|
|
let pipeline_create_info = pipeline_create_info.push_constant_ranges(push_constant_range);
|
2023-02-16 14:57:20 +11:00
|
|
|
|
2022-12-22 13:39:31 +11:00
|
|
|
let layout = unsafe { device.create_pipeline_layout(&pipeline_create_info, None)? };
|
2022-12-10 17:25:36 +11:00
|
|
|
|
2024-08-01 15:23:18 +10:00
|
|
|
let pool_info = vk::DescriptorPoolCreateInfo::default()
|
2024-09-12 13:44:33 +10:00
|
|
|
.max_sets(replicas * 2)
|
2023-02-17 09:33:47 +11:00
|
|
|
.pool_sizes(&descriptors.pool_sizes);
|
2023-01-13 16:07:03 +11:00
|
|
|
|
2023-01-13 17:48:04 +11:00
|
|
|
let pool = unsafe { device.create_descriptor_pool(&pool_info, None)? };
|
2022-12-10 17:25:36 +11:00
|
|
|
|
|
|
|
let mut descriptor_sets = Vec::new();
|
2024-08-01 15:23:18 +10:00
|
|
|
let alloc_info = vk::DescriptorSetAllocateInfo::default()
|
2022-12-10 17:25:36 +11:00
|
|
|
.descriptor_pool(pool)
|
2023-02-17 09:33:47 +11:00
|
|
|
.set_layouts(&descriptor_set_layout);
|
2022-12-10 17:25:36 +11:00
|
|
|
|
|
|
|
for _ in 0..replicas {
|
2023-01-13 16:07:03 +11:00
|
|
|
let set = unsafe { device.allocate_descriptor_sets(&alloc_info)? };
|
|
|
|
descriptor_sets.push(set)
|
2022-12-10 17:25:36 +11:00
|
|
|
}
|
|
|
|
|
2022-12-22 13:39:31 +11:00
|
|
|
let descriptor_sets: Vec<vk::DescriptorSet> =
|
|
|
|
descriptor_sets.into_iter().flatten().collect();
|
2022-12-10 17:25:36 +11:00
|
|
|
|
2024-09-12 13:44:33 +10:00
|
|
|
let mut descriptor_sets_alt = Vec::new();
|
|
|
|
let alloc_info = vk::DescriptorSetAllocateInfo::default()
|
|
|
|
.descriptor_pool(pool)
|
|
|
|
.set_layouts(&descriptor_set_layout);
|
|
|
|
|
|
|
|
for _ in 0..replicas {
|
|
|
|
let set = unsafe { device.allocate_descriptor_sets(&alloc_info)? };
|
|
|
|
descriptor_sets_alt.push(set)
|
|
|
|
}
|
|
|
|
|
|
|
|
let descriptor_sets_alt: Vec<vk::DescriptorSet> =
|
|
|
|
descriptor_sets_alt.into_iter().flatten().collect();
|
|
|
|
|
2023-01-16 03:08:13 +11:00
|
|
|
Ok(PipelineLayoutObjects {
|
2022-12-10 17:25:36 +11:00
|
|
|
layout,
|
2024-08-01 15:23:18 +10:00
|
|
|
_descriptor_set_layout: descriptor_set_layout,
|
2022-12-10 17:25:36 +11:00
|
|
|
descriptor_sets,
|
2024-09-12 13:44:33 +10:00
|
|
|
descriptor_sets_alt,
|
2024-08-01 15:23:18 +10:00
|
|
|
_pool: pool,
|
2023-01-16 03:08:13 +11:00
|
|
|
})
|
2022-12-10 17:25:36 +11:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub struct VulkanShaderModule {
|
|
|
|
shader: vk::ShaderModule,
|
|
|
|
device: ash::Device,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl VulkanShaderModule {
|
2022-12-22 13:39:31 +11:00
|
|
|
pub fn new(
|
|
|
|
device: &ash::Device,
|
|
|
|
info: &vk::ShaderModuleCreateInfo,
|
|
|
|
) -> error::Result<VulkanShaderModule> {
|
2022-12-10 17:25:36 +11:00
|
|
|
Ok(VulkanShaderModule {
|
|
|
|
shader: unsafe { device.create_shader_module(info, None)? },
|
2022-12-22 13:39:31 +11:00
|
|
|
device: device.clone(),
|
2022-12-10 17:25:36 +11:00
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Drop for VulkanShaderModule {
|
|
|
|
fn drop(&mut self) {
|
2022-12-22 13:39:31 +11:00
|
|
|
unsafe { self.device.destroy_shader_module(self.shader, None) }
|
2022-12-10 17:25:36 +11:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub struct VulkanGraphicsPipeline {
|
2022-12-29 16:50:48 +11:00
|
|
|
pub layout: PipelineLayoutObjects,
|
2024-09-12 13:44:33 +10:00
|
|
|
pub pipelines: FastHashMap<vk::Format, vk::Pipeline>,
|
|
|
|
pub render_passes: FastHashMap<vk::Format, Option<VulkanRenderPass>>,
|
2023-02-09 13:21:40 +11:00
|
|
|
device: Arc<ash::Device>,
|
|
|
|
vertex: VulkanShaderModule,
|
|
|
|
fragment: VulkanShaderModule,
|
|
|
|
cache: vk::PipelineCache,
|
2024-09-12 13:44:33 +10:00
|
|
|
use_render_pass: bool,
|
2022-12-10 17:25:36 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
impl VulkanGraphicsPipeline {
|
2023-02-09 13:21:40 +11:00
|
|
|
fn create_pipeline(
|
2022-12-22 13:39:31 +11:00
|
|
|
device: &ash::Device,
|
|
|
|
cache: &vk::PipelineCache,
|
2023-02-09 13:21:40 +11:00
|
|
|
pipeline_layout: &PipelineLayoutObjects,
|
|
|
|
vertex_module: &VulkanShaderModule,
|
|
|
|
fragment_module: &VulkanShaderModule,
|
|
|
|
render_pass: Option<&VulkanRenderPass>,
|
|
|
|
) -> error::Result<vk::Pipeline> {
|
2024-08-01 15:23:18 +10:00
|
|
|
let input_assembly = vk::PipelineInputAssemblyStateCreateInfo::default()
|
2023-02-17 09:33:47 +11:00
|
|
|
.topology(vk::PrimitiveTopology::TRIANGLE_STRIP);
|
2022-12-10 17:25:36 +11:00
|
|
|
|
2022-12-22 13:39:31 +11:00
|
|
|
let vao_state = [
|
|
|
|
vk::VertexInputAttributeDescription {
|
|
|
|
location: 0,
|
|
|
|
binding: 0,
|
|
|
|
format: vk::Format::R32G32_SFLOAT,
|
2024-02-22 16:41:29 +11:00
|
|
|
offset: offset_of!(VertexInput, position) as u32,
|
2022-12-22 13:39:31 +11:00
|
|
|
},
|
|
|
|
vk::VertexInputAttributeDescription {
|
|
|
|
location: 1,
|
|
|
|
binding: 0,
|
|
|
|
format: vk::Format::R32G32_SFLOAT,
|
2024-02-22 16:41:29 +11:00
|
|
|
offset: offset_of!(VertexInput, texcoord) as u32,
|
2022-12-22 13:39:31 +11:00
|
|
|
},
|
|
|
|
];
|
2022-12-10 17:25:36 +11:00
|
|
|
|
2024-08-01 15:23:18 +10:00
|
|
|
let input_binding = vk::VertexInputBindingDescription::default()
|
2022-12-10 17:25:36 +11:00
|
|
|
.binding(0)
|
2024-02-22 16:41:29 +11:00
|
|
|
.stride(std::mem::size_of::<VertexInput>() as u32)
|
2023-02-16 14:57:20 +11:00
|
|
|
.input_rate(vk::VertexInputRate::VERTEX);
|
2022-12-10 17:25:36 +11:00
|
|
|
|
2024-08-01 15:23:18 +10:00
|
|
|
let input_binding = [input_binding];
|
|
|
|
let pipeline_input_state = vk::PipelineVertexInputStateCreateInfo::default()
|
2023-01-13 16:07:03 +11:00
|
|
|
.vertex_binding_descriptions(&input_binding)
|
2023-02-17 09:33:47 +11:00
|
|
|
.vertex_attribute_descriptions(&vao_state);
|
2022-12-10 17:25:36 +11:00
|
|
|
|
2024-08-01 15:23:18 +10:00
|
|
|
let raster_state = vk::PipelineRasterizationStateCreateInfo::default()
|
2022-12-10 17:25:36 +11:00
|
|
|
.polygon_mode(vk::PolygonMode::FILL)
|
|
|
|
.cull_mode(vk::CullModeFlags::NONE)
|
|
|
|
.front_face(vk::FrontFace::COUNTER_CLOCKWISE)
|
|
|
|
.depth_clamp_enable(false)
|
|
|
|
.rasterizer_discard_enable(false)
|
|
|
|
.depth_bias_enable(false)
|
2023-02-17 09:33:47 +11:00
|
|
|
.line_width(1.0);
|
2022-12-10 17:25:36 +11:00
|
|
|
|
2024-08-01 15:23:18 +10:00
|
|
|
let attachments = vk::PipelineColorBlendAttachmentState::default()
|
2023-01-13 16:07:03 +11:00
|
|
|
.blend_enable(false)
|
2023-02-16 14:57:20 +11:00
|
|
|
.color_write_mask(vk::ColorComponentFlags::from_raw(0xf));
|
2023-01-13 16:07:03 +11:00
|
|
|
|
2024-08-01 15:23:18 +10:00
|
|
|
let attachments = [attachments];
|
2023-02-17 09:33:47 +11:00
|
|
|
let blend_state =
|
2024-08-01 15:23:18 +10:00
|
|
|
vk::PipelineColorBlendStateCreateInfo::default().attachments(&attachments);
|
2022-12-10 17:25:36 +11:00
|
|
|
|
2024-08-01 15:23:18 +10:00
|
|
|
let viewport_state = vk::PipelineViewportStateCreateInfo::default()
|
2022-12-10 17:25:36 +11:00
|
|
|
.viewport_count(1)
|
2023-02-17 09:33:47 +11:00
|
|
|
.scissor_count(1);
|
2022-12-10 17:25:36 +11:00
|
|
|
|
2024-08-01 15:23:18 +10:00
|
|
|
let depth_stencil_state = vk::PipelineDepthStencilStateCreateInfo::default()
|
2022-12-10 17:25:36 +11:00
|
|
|
.depth_test_enable(false)
|
|
|
|
.depth_write_enable(false)
|
|
|
|
.stencil_test_enable(false)
|
|
|
|
.depth_bounds_test_enable(false)
|
|
|
|
.min_depth_bounds(1.0)
|
2023-02-17 09:33:47 +11:00
|
|
|
.max_depth_bounds(1.0);
|
2022-12-10 17:25:36 +11:00
|
|
|
|
2024-08-01 15:23:18 +10:00
|
|
|
let multisample_state = vk::PipelineMultisampleStateCreateInfo::default()
|
2023-02-17 09:33:47 +11:00
|
|
|
.rasterization_samples(vk::SampleCountFlags::TYPE_1);
|
2022-12-10 17:25:36 +11:00
|
|
|
|
2023-01-13 16:07:03 +11:00
|
|
|
let states = [vk::DynamicState::VIEWPORT, vk::DynamicState::SCISSOR];
|
2024-08-01 15:23:18 +10:00
|
|
|
let dynamic_state = vk::PipelineDynamicStateCreateInfo::default().dynamic_states(&states);
|
2022-12-10 17:25:36 +11:00
|
|
|
|
|
|
|
let shader_stages = [
|
2024-08-01 15:23:18 +10:00
|
|
|
vk::PipelineShaderStageCreateInfo::default()
|
2022-12-10 17:25:36 +11:00
|
|
|
.stage(vk::ShaderStageFlags::VERTEX)
|
2023-01-16 03:08:13 +11:00
|
|
|
.name(ENTRY_POINT)
|
2023-02-17 09:33:47 +11:00
|
|
|
.module(vertex_module.shader),
|
2024-08-01 15:23:18 +10:00
|
|
|
vk::PipelineShaderStageCreateInfo::default()
|
2022-12-10 17:25:36 +11:00
|
|
|
.stage(vk::ShaderStageFlags::FRAGMENT)
|
2023-01-16 03:08:13 +11:00
|
|
|
.name(ENTRY_POINT)
|
2023-02-17 09:33:47 +11:00
|
|
|
.module(fragment_module.shader),
|
2022-12-10 17:25:36 +11:00
|
|
|
];
|
|
|
|
|
2024-08-01 15:23:18 +10:00
|
|
|
let mut pipeline_info = vk::GraphicsPipelineCreateInfo::default()
|
2022-12-10 17:25:36 +11:00
|
|
|
.stages(&shader_stages)
|
|
|
|
.vertex_input_state(&pipeline_input_state)
|
|
|
|
.input_assembly_state(&input_assembly)
|
|
|
|
.rasterization_state(&raster_state)
|
|
|
|
.color_blend_state(&blend_state)
|
|
|
|
.multisample_state(&multisample_state)
|
|
|
|
.viewport_state(&viewport_state)
|
|
|
|
.depth_stencil_state(&depth_stencil_state)
|
|
|
|
.dynamic_state(&dynamic_state)
|
2023-01-26 15:45:10 +11:00
|
|
|
.layout(pipeline_layout.layout);
|
|
|
|
|
2023-02-09 13:21:40 +11:00
|
|
|
if let Some(render_pass) = render_pass {
|
|
|
|
pipeline_info = pipeline_info.render_pass(render_pass.handle)
|
2023-01-26 15:45:10 +11:00
|
|
|
}
|
|
|
|
|
2022-12-10 17:25:36 +11:00
|
|
|
let pipeline = unsafe {
|
|
|
|
// panic_safety: if this is successful this should return 1 pipelines.
|
2022-12-22 13:39:31 +11:00
|
|
|
device
|
2024-08-01 15:23:18 +10:00
|
|
|
.create_graphics_pipelines(*cache, &[pipeline_info], None)
|
2023-02-15 11:24:42 +11:00
|
|
|
.map_err(|e| e.1)?[0]
|
2022-12-10 17:25:36 +11:00
|
|
|
};
|
|
|
|
|
2023-02-09 13:21:40 +11:00
|
|
|
Ok(pipeline)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn new(
|
|
|
|
device: &Arc<ash::Device>,
|
|
|
|
shader_assembly: &ShaderCompilerOutput<Vec<u32>>,
|
|
|
|
reflection: &ShaderReflection,
|
|
|
|
replicas: u32,
|
|
|
|
render_pass_format: vk::Format,
|
2023-02-16 09:40:24 +11:00
|
|
|
bypass_cache: bool,
|
2023-02-09 13:21:40 +11:00
|
|
|
) -> error::Result<VulkanGraphicsPipeline> {
|
|
|
|
let pipeline_layout = PipelineLayoutObjects::new(reflection, replicas, device)?;
|
|
|
|
|
2023-02-17 09:33:47 +11:00
|
|
|
let vertex_info =
|
2024-08-01 15:23:18 +10:00
|
|
|
vk::ShaderModuleCreateInfo::default().code(shader_assembly.vertex.as_ref());
|
2023-02-17 09:33:47 +11:00
|
|
|
let fragment_info =
|
2024-08-01 15:23:18 +10:00
|
|
|
vk::ShaderModuleCreateInfo::default().code(shader_assembly.fragment.as_ref());
|
2023-02-09 13:21:40 +11:00
|
|
|
|
|
|
|
let vertex_module = VulkanShaderModule::new(device, &vertex_info)?;
|
|
|
|
let fragment_module = VulkanShaderModule::new(device, &fragment_info)?;
|
|
|
|
|
|
|
|
let mut render_pass = None;
|
2024-09-12 13:44:33 +10:00
|
|
|
let mut use_render_pass = false;
|
2023-02-09 13:21:40 +11:00
|
|
|
if render_pass_format != vk::Format::UNDEFINED {
|
|
|
|
render_pass = Some(VulkanRenderPass::create_render_pass(
|
|
|
|
device,
|
|
|
|
render_pass_format,
|
|
|
|
)?);
|
2024-09-12 13:44:33 +10:00
|
|
|
use_render_pass = true;
|
2023-02-09 13:21:40 +11:00
|
|
|
}
|
|
|
|
|
2023-02-13 14:36:50 +11:00
|
|
|
let (pipeline, pipeline_cache) = cache_pipeline(
|
|
|
|
"vulkan",
|
|
|
|
&[&shader_assembly.vertex, &shader_assembly.fragment],
|
|
|
|
|pipeline_data| {
|
2024-08-01 15:23:18 +10:00
|
|
|
let mut cache_info = vk::PipelineCacheCreateInfo::default();
|
2023-02-13 14:36:50 +11:00
|
|
|
if let Some(pipeline_data) = pipeline_data.as_ref() {
|
|
|
|
cache_info = cache_info.initial_data(pipeline_data);
|
|
|
|
}
|
2023-02-16 14:57:20 +11:00
|
|
|
let cache_info = cache_info;
|
2023-02-13 14:36:50 +11:00
|
|
|
|
|
|
|
let pipeline_cache = unsafe { device.create_pipeline_cache(&cache_info, None)? };
|
|
|
|
|
|
|
|
let pipeline = Self::create_pipeline(
|
|
|
|
&device,
|
|
|
|
&pipeline_cache,
|
|
|
|
&pipeline_layout,
|
|
|
|
&vertex_module,
|
|
|
|
&fragment_module,
|
|
|
|
render_pass.as_ref(),
|
|
|
|
)?;
|
|
|
|
Ok::<_, FilterChainError>((pipeline, pipeline_cache))
|
|
|
|
},
|
|
|
|
|(_pipeline, cache)| unsafe { Ok(device.get_pipeline_cache_data(*cache)?) },
|
2023-02-16 09:40:24 +11:00
|
|
|
bypass_cache,
|
2023-02-09 13:21:40 +11:00
|
|
|
)?;
|
|
|
|
|
2024-09-12 13:44:33 +10:00
|
|
|
let mut pipelines = FastHashMap::default();
|
|
|
|
let mut render_passes = FastHashMap::default();
|
|
|
|
|
|
|
|
pipelines.insert(render_pass_format, pipeline);
|
|
|
|
render_passes.insert(render_pass_format, render_pass);
|
|
|
|
|
2022-12-10 17:25:36 +11:00
|
|
|
Ok(VulkanGraphicsPipeline {
|
2023-02-09 13:21:40 +11:00
|
|
|
device: Arc::clone(device),
|
2022-12-10 17:25:36 +11:00
|
|
|
layout: pipeline_layout,
|
2024-09-12 13:44:33 +10:00
|
|
|
pipelines,
|
|
|
|
render_passes,
|
2023-02-09 13:21:40 +11:00
|
|
|
vertex: vertex_module,
|
|
|
|
fragment: fragment_module,
|
2023-02-13 14:36:50 +11:00
|
|
|
cache: pipeline_cache,
|
2024-09-12 13:44:33 +10:00
|
|
|
use_render_pass,
|
2022-12-10 17:25:36 +11:00
|
|
|
})
|
|
|
|
}
|
2023-01-26 15:45:10 +11:00
|
|
|
|
2023-02-09 13:21:40 +11:00
|
|
|
pub(crate) fn recompile(&mut self, format: vk::Format) -> error::Result<()> {
|
2024-09-12 13:44:33 +10:00
|
|
|
let new_renderpass = if self.use_render_pass {
|
2023-02-09 13:21:40 +11:00
|
|
|
Some(VulkanRenderPass::create_render_pass(&self.device, format)?)
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
};
|
|
|
|
|
2024-09-12 13:44:33 +10:00
|
|
|
let new_pipeline = Self::create_pipeline(
|
2023-02-09 13:21:40 +11:00
|
|
|
&self.device,
|
|
|
|
&self.cache,
|
|
|
|
&self.layout,
|
|
|
|
&self.vertex,
|
|
|
|
&self.fragment,
|
|
|
|
new_renderpass.as_ref(),
|
|
|
|
)?;
|
|
|
|
|
2024-09-12 13:44:33 +10:00
|
|
|
self.render_passes.insert(format, new_renderpass);
|
|
|
|
self.pipelines.insert(format, new_pipeline);
|
2023-02-09 13:21:40 +11:00
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
2023-01-26 15:45:10 +11:00
|
|
|
#[inline(always)]
|
2023-01-29 18:30:58 +11:00
|
|
|
pub(crate) fn begin_rendering(
|
|
|
|
&self,
|
2023-02-08 15:08:44 +11:00
|
|
|
output: &RenderTarget<OutputImage>,
|
2024-09-12 13:44:33 +10:00
|
|
|
format: vk::Format,
|
2023-01-29 18:30:58 +11:00
|
|
|
cmd: vk::CommandBuffer,
|
|
|
|
) -> error::Result<Option<vk::Framebuffer>> {
|
2024-09-12 13:44:33 +10:00
|
|
|
if let Some(Some(render_pass)) = &self.render_passes.get(&format) {
|
2023-01-26 15:45:10 +11:00
|
|
|
let attachments = [output.output.image_view];
|
|
|
|
let framebuffer = unsafe {
|
2023-12-16 22:28:41 +11:00
|
|
|
self.device.create_framebuffer(
|
2024-08-01 15:23:18 +10:00
|
|
|
&vk::FramebufferCreateInfo::default()
|
2023-01-26 15:45:10 +11:00
|
|
|
.render_pass(render_pass.handle)
|
|
|
|
.attachments(&attachments)
|
|
|
|
.width(output.output.size.width)
|
|
|
|
.height(output.output.size.height)
|
2023-02-17 09:33:47 +11:00
|
|
|
.layers(1),
|
2023-01-26 15:45:10 +11:00
|
|
|
None,
|
|
|
|
)?
|
|
|
|
};
|
|
|
|
|
|
|
|
let clear_values = [vk::ClearValue {
|
|
|
|
color: vk::ClearColorValue {
|
2023-01-29 18:30:58 +11:00
|
|
|
float32: [0.0, 0.0, 0.0, 0.0],
|
|
|
|
},
|
2023-01-26 15:45:10 +11:00
|
|
|
}];
|
|
|
|
|
2024-08-01 15:23:18 +10:00
|
|
|
let render_pass_info = vk::RenderPassBeginInfo::default()
|
2023-01-26 15:45:10 +11:00
|
|
|
.framebuffer(framebuffer)
|
|
|
|
.render_pass(render_pass.handle)
|
|
|
|
.clear_values(&clear_values)
|
|
|
|
// always render into the full output, regardless of viewport settings.
|
|
|
|
.render_area(vk::Rect2D {
|
2023-01-29 18:30:58 +11:00
|
|
|
offset: vk::Offset2D { x: 0, y: 0 },
|
2023-01-26 15:45:10 +11:00
|
|
|
extent: output.output.size.into(),
|
2023-02-17 09:33:47 +11:00
|
|
|
});
|
2023-01-26 15:45:10 +11:00
|
|
|
unsafe {
|
2024-02-06 17:32:08 +11:00
|
|
|
self.device.cmd_begin_render_pass(
|
|
|
|
cmd,
|
|
|
|
&render_pass_info,
|
|
|
|
vk::SubpassContents::INLINE,
|
|
|
|
);
|
2023-01-26 15:45:10 +11:00
|
|
|
}
|
|
|
|
Ok(Some(framebuffer))
|
|
|
|
} else {
|
2024-08-01 15:23:18 +10:00
|
|
|
let attachments = [vk::RenderingAttachmentInfo::default()
|
2023-01-26 15:45:10 +11:00
|
|
|
.load_op(vk::AttachmentLoadOp::DONT_CARE)
|
|
|
|
.store_op(vk::AttachmentStoreOp::STORE)
|
|
|
|
.image_layout(vk::ImageLayout::COLOR_ATTACHMENT_OPTIMAL)
|
2024-08-01 15:23:18 +10:00
|
|
|
.image_view(output.output.image_view)];
|
2023-01-26 15:45:10 +11:00
|
|
|
|
2024-08-01 15:23:18 +10:00
|
|
|
let rendering_info = vk::RenderingInfo::default()
|
2023-01-26 15:45:10 +11:00
|
|
|
.layer_count(1)
|
|
|
|
.render_area(vk::Rect2D {
|
|
|
|
offset: vk::Offset2D { x: 0, y: 0 },
|
|
|
|
extent: output.output.size.into(),
|
|
|
|
})
|
2023-02-17 09:33:47 +11:00
|
|
|
.color_attachments(&attachments);
|
2023-01-26 15:45:10 +11:00
|
|
|
|
|
|
|
unsafe {
|
2023-12-16 22:28:41 +11:00
|
|
|
self.device.cmd_begin_rendering(cmd, &rendering_info);
|
2023-01-26 15:45:10 +11:00
|
|
|
}
|
|
|
|
Ok(None)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-12-16 22:28:41 +11:00
|
|
|
pub(crate) fn end_rendering(&self, cmd: vk::CommandBuffer) {
|
2023-01-26 15:45:10 +11:00
|
|
|
unsafe {
|
2024-09-12 13:44:33 +10:00
|
|
|
if !self.use_render_pass {
|
2023-12-16 22:28:41 +11:00
|
|
|
self.device.cmd_end_rendering(cmd);
|
2023-01-26 15:45:10 +11:00
|
|
|
} else {
|
2023-12-16 22:28:41 +11:00
|
|
|
self.device.cmd_end_render_pass(cmd)
|
2023-01-26 15:45:10 +11:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-12-22 13:39:31 +11:00
|
|
|
}
|
2023-02-13 14:36:50 +11:00
|
|
|
|
|
|
|
impl Drop for VulkanGraphicsPipeline {
|
|
|
|
fn drop(&mut self) {
|
|
|
|
unsafe {
|
2024-09-12 13:44:33 +10:00
|
|
|
for (_, pipeline) in self.pipelines.iter_mut() {
|
|
|
|
if *pipeline != vk::Pipeline::null() {
|
|
|
|
self.device.destroy_pipeline(*pipeline, None)
|
|
|
|
}
|
2023-02-13 14:36:50 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
if self.cache != vk::PipelineCache::null() {
|
|
|
|
self.device.destroy_pipeline_cache(self.cache, None)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|