From 9437a56807b37438a57ac97197a929ca8b233367 Mon Sep 17 00:00:00 2001 From: kossLAN Date: Fri, 29 May 2026 21:35:40 -0400 Subject: [PATCH] vulkan: split renderer pipelines --- src/gfx_apis/vulkan/renderer.rs | 268 +------------------- src/gfx_apis/vulkan/renderer/pipelines.rs | 282 ++++++++++++++++++++++ 2 files changed, 289 insertions(+), 261 deletions(-) create mode 100644 src/gfx_apis/vulkan/renderer/pipelines.rs diff --git a/src/gfx_apis/vulkan/renderer.rs b/src/gfx_apis/vulkan/renderer.rs index 9e8ceabb..9f89d3d1 100644 --- a/src/gfx_apis/vulkan/renderer.rs +++ b/src/gfx_apis/vulkan/renderer.rs @@ -1,6 +1,7 @@ mod color; mod op; mod pipeline_cache; +mod pipelines; mod paint_region; use { @@ -10,7 +11,7 @@ use { VulkanRoundedTexOp, VulkanTexOp, }, paint_region::{PaintRegion, Point, constrain_to_fb}, - pipeline_cache::{FillPipelines, OutPipelineKey, TexPipelineKey, TexPipelines}, + pipeline_cache::{FillPipelines, OutPipelineKey, TexPipelines}, crate::{ async_engine::{AsyncEngine, SpawnedFuture}, cmm::{ @@ -19,8 +20,8 @@ use { }, cpu_worker::PendingJob, gfx_api::{ - AcquireSync, AlphaMode, BufferResv, BufferResvUser, FdSync, GfxApiOpt, GfxBlendBuffer, - GfxFormat, GfxTexture, GfxWriteModifier, ReleaseSync, + AcquireSync, BufferResv, BufferResvUser, FdSync, GfxApiOpt, GfxBlendBuffer, GfxFormat, + GfxTexture, GfxWriteModifier, ReleaseSync, }, gfx_apis::vulkan::{ VulkanError, VulkanSync, VulkanTimelineSemaphore, @@ -30,9 +31,9 @@ use { descriptor::VulkanDescriptorSetLayout, descriptor_buffer::VulkanDescriptorBufferWriter, device::VulkanDevice, - eotfs::{EOTF_LINEAR, EotfExt, VulkanEotf}, + eotfs::VulkanEotf, image::{QueueFamily, QueueState, QueueTransfer, VulkanImage, VulkanImageMemory}, - pipeline::{PipelineCreateInfo, VulkanPipeline}, + pipeline::VulkanPipeline, sampler::VulkanSampler, semaphore::VulkanSemaphore, shaders::{ @@ -78,7 +79,7 @@ use { }, }, isnt::std_1::{collections::IsntHashMapExt, primitive::IsntSliceExt}, - linearize::{Linearize, LinearizeExt, StaticMap, static_map}, + linearize::{Linearize, LinearizeExt, StaticMap}, std::{ any::Any, borrow::Cow, @@ -378,261 +379,6 @@ impl VulkanDevice { } impl VulkanRenderer { - fn get_or_create_fill_pipelines( - &self, - format: vk::Format, - ) -> Result { - if let Some(pl) = self.fill_pipelines.get(&format) { - return Ok(pl); - } - let create_fill_pipeline = |src_has_alpha| { - let push_size = if self.device.descriptor_buffer.is_some() { - size_of::() - } else { - size_of::() - }; - let info = PipelineCreateInfo { - format, - vert: self.fill_vert_shader.clone(), - frag: self.fill_frag_shader.clone(), - blend: src_has_alpha, - src_has_alpha, - has_alpha_mult: false, - alpha_mode: AlphaMode::PremultipliedOptical, - // all transformations are applied in the compositor - eotf: EOTF_LINEAR, - inv_eotf: EOTF_LINEAR, - descriptor_set_layouts: Default::default(), - has_color_management_data: false, - }; - self.device.create_pipeline2(info, push_size) - }; - let fill_pipelines = Rc::new(static_map! { - TexSourceType::HasAlpha => create_fill_pipeline(true)?, - TexSourceType::Opaque => create_fill_pipeline(false)?, - }); - self.fill_pipelines.set(format, fill_pipelines.clone()); - Ok(fill_pipelines) - } - - fn get_or_create_rounded_fill_pipelines( - &self, - format: vk::Format, - ) -> Result { - if let Some(pl) = self.rounded_fill_pipelines.get(&format) { - return Ok(pl); - } - let create_pipeline = |src_has_alpha| { - let push_size = if self.device.descriptor_buffer.is_some() { - size_of::() - } else { - size_of::() - }; - let info = PipelineCreateInfo { - format, - vert: self.rounded_fill_vert_shader.clone(), - frag: self.rounded_fill_frag_shader.clone(), - blend: src_has_alpha, - src_has_alpha, - has_alpha_mult: false, - alpha_mode: AlphaMode::PremultipliedOptical, - eotf: EOTF_LINEAR, - inv_eotf: EOTF_LINEAR, - descriptor_set_layouts: Default::default(), - has_color_management_data: false, - }; - self.device.create_pipeline2(info, push_size) - }; - let pipelines = Rc::new(static_map! { - TexSourceType::HasAlpha => create_pipeline(true)?, - TexSourceType::Opaque => create_pipeline(false)?, - }); - self.rounded_fill_pipelines.set(format, pipelines.clone()); - Ok(pipelines) - } - - fn get_or_create_rounded_tex_pipelines( - &self, - format: vk::Format, - target_cd: &ColorDescription, - ) -> Rc { - let eotf = target_cd.eotf.to_vulkan(); - let pipelines = &self.rounded_tex_pipelines[eotf]; - match pipelines.get(&format) { - Some(pl) => pl, - _ => { - let pl = Rc::new(TexPipelines { - format, - eotf, - pipelines: Default::default(), - }); - pipelines.set(format, pl.clone()); - pl - } - } - } - - fn get_or_create_rounded_tex_pipeline( - &self, - pipelines: &TexPipelines, - tex_cd: &ColorDescription, - tex_copy_type: TexCopyType, - tex_source_type: TexSourceType, - mut tex_alpha_mode: AlphaMode, - has_color_management_data: bool, - ) -> Result, VulkanError> { - if tex_source_type == TexSourceType::Opaque { - tex_alpha_mode = AlphaMode::PremultipliedElectrical; - } - let key = TexPipelineKey { - tex_copy_type, - tex_source_type, - tex_alpha_mode, - eotf: tex_cd.eotf.to_vulkan(), - has_color_management_data, - }; - if let Some(pl) = pipelines.pipelines.get(&key) { - return Ok(pl); - } - let has_alpha_mult = match tex_copy_type { - TexCopyType::Identity => false, - TexCopyType::Multiply => true, - }; - let push_size = if self.device.descriptor_buffer.is_some() { - size_of::() - } else { - size_of::() - }; - let info = PipelineCreateInfo { - format: pipelines.format, - vert: self.rounded_tex_vert_shader.clone(), - frag: self.rounded_tex_frag_shader.clone(), - blend: true, // always blend since corners are transparent - src_has_alpha: true, // rounding makes everything have alpha - has_alpha_mult, - alpha_mode: key.tex_alpha_mode, - eotf: key.eotf.to_vulkan(), - inv_eotf: pipelines.eotf.to_vulkan(), - descriptor_set_layouts: self.tex_descriptor_set_layouts.clone(), - has_color_management_data, - }; - let pl = self.device.create_pipeline2(info, push_size)?; - pipelines.pipelines.set(key, pl.clone()); - Ok(pl) - } - - fn get_or_create_tex_pipelines( - &self, - format: vk::Format, - target_cd: &ColorDescription, - ) -> Rc { - let eotf = target_cd.eotf.to_vulkan(); - let pipelines = &self.tex_pipelines[eotf]; - match pipelines.get(&format) { - Some(pl) => pl, - _ => { - let pl = Rc::new(TexPipelines { - format, - eotf, - pipelines: Default::default(), - }); - pipelines.set(format, pl.clone()); - pl - } - } - } - - fn get_or_create_tex_pipeline( - &self, - pipelines: &TexPipelines, - tex_cd: &ColorDescription, - tex_copy_type: TexCopyType, - tex_source_type: TexSourceType, - mut tex_alpha_mode: AlphaMode, - has_color_management_data: bool, - ) -> Result, VulkanError> { - if tex_source_type == TexSourceType::Opaque { - tex_alpha_mode = AlphaMode::PremultipliedElectrical; - } - let key = TexPipelineKey { - tex_copy_type, - tex_source_type, - tex_alpha_mode, - eotf: tex_cd.eotf.to_vulkan(), - has_color_management_data, - }; - if let Some(pl) = pipelines.pipelines.get(&key) { - return Ok(pl); - } - let src_has_alpha = match tex_source_type { - TexSourceType::Opaque => false, - TexSourceType::HasAlpha => true, - }; - let has_alpha_mult = match tex_copy_type { - TexCopyType::Identity => false, - TexCopyType::Multiply => true, - }; - let push_size = if self.device.descriptor_buffer.is_some() { - size_of::() - } else { - size_of::() - }; - let info = PipelineCreateInfo { - format: pipelines.format, - vert: self.tex_vert_shader.clone(), - frag: self.tex_frag_shader.clone(), - blend: src_has_alpha || has_alpha_mult, - src_has_alpha, - has_alpha_mult, - alpha_mode: key.tex_alpha_mode, - eotf: key.eotf.to_vulkan(), - inv_eotf: pipelines.eotf.to_vulkan(), - descriptor_set_layouts: self.tex_descriptor_set_layouts.clone(), - has_color_management_data, - }; - let pl = self.device.create_pipeline2(info, push_size)?; - pipelines.pipelines.set(key, pl.clone()); - Ok(pl) - } - - fn get_or_create_out_pipeline( - &self, - format: vk::Format, - bb_cd: &ColorDescription, - fb_cd: &ColorDescription, - has_color_management_data: bool, - ) -> Result, VulkanError> { - let key = OutPipelineKey { - format, - eotf: bb_cd.eotf.to_vulkan(), - has_color_management_data, - }; - let fb_eotf = fb_cd.eotf.to_vulkan(); - let pipelines = &self.out_pipelines[fb_eotf]; - if let Some(pl) = pipelines.get(&key) { - return Ok(pl); - } - let mut descriptor_set_layouts = ArrayVec::new(); - descriptor_set_layouts.push(self.out_descriptor_set_layout.clone().unwrap()); - let out = self - .device - .create_pipeline::(PipelineCreateInfo { - format: key.format, - vert: self.out_vert_shader.clone().unwrap(), - frag: self.out_frag_shader.clone().unwrap(), - blend: false, - src_has_alpha: true, - has_alpha_mult: false, - alpha_mode: AlphaMode::PremultipliedElectrical, - eotf: key.eotf.to_vulkan(), - inv_eotf: fb_eotf.to_vulkan(), - descriptor_set_layouts, - has_color_management_data, - })?; - pipelines.set(key, out.clone()); - Ok(out) - } - pub(super) fn allocate_point(&self) -> u64 { self.last_point.fetch_add(1) + 1 } diff --git a/src/gfx_apis/vulkan/renderer/pipelines.rs b/src/gfx_apis/vulkan/renderer/pipelines.rs new file mode 100644 index 00000000..29b7429a --- /dev/null +++ b/src/gfx_apis/vulkan/renderer/pipelines.rs @@ -0,0 +1,282 @@ +use { + super::{ + VulkanRenderer, + op::{TexCopyType, TexSourceType}, + pipeline_cache::{FillPipelines, OutPipelineKey, TexPipelineKey, TexPipelines}, + }, + crate::{ + cmm::cmm_description::ColorDescription, + gfx_api::AlphaMode, + gfx_apis::vulkan::{ + VulkanError, + eotfs::{EOTF_LINEAR, EotfExt}, + pipeline::{PipelineCreateInfo, VulkanPipeline}, + shaders::{ + FillPushConstants, LegacyFillPushConstants, LegacyRoundedFillPushConstants, + LegacyRoundedTexPushConstants, LegacyTexPushConstants, OutPushConstants, + RoundedFillPushConstants, RoundedTexPushConstants, TexPushConstants, + }, + }, + }, + arrayvec::ArrayVec, + ash::vk, + linearize::static_map, + std::{mem::size_of, rc::Rc}, +}; + +impl VulkanRenderer { + pub(super) fn get_or_create_fill_pipelines( + &self, + format: vk::Format, + ) -> Result { + if let Some(pl) = self.fill_pipelines.get(&format) { + return Ok(pl); + } + let create_fill_pipeline = |src_has_alpha| { + let push_size = if self.device.descriptor_buffer.is_some() { + size_of::() + } else { + size_of::() + }; + let info = PipelineCreateInfo { + format, + vert: self.fill_vert_shader.clone(), + frag: self.fill_frag_shader.clone(), + blend: src_has_alpha, + src_has_alpha, + has_alpha_mult: false, + alpha_mode: AlphaMode::PremultipliedOptical, + // all transformations are applied in the compositor + eotf: EOTF_LINEAR, + inv_eotf: EOTF_LINEAR, + descriptor_set_layouts: Default::default(), + has_color_management_data: false, + }; + self.device.create_pipeline2(info, push_size) + }; + let fill_pipelines = Rc::new(static_map! { + TexSourceType::HasAlpha => create_fill_pipeline(true)?, + TexSourceType::Opaque => create_fill_pipeline(false)?, + }); + self.fill_pipelines.set(format, fill_pipelines.clone()); + Ok(fill_pipelines) + } + + pub(super) fn get_or_create_rounded_fill_pipelines( + &self, + format: vk::Format, + ) -> Result { + if let Some(pl) = self.rounded_fill_pipelines.get(&format) { + return Ok(pl); + } + let create_pipeline = |src_has_alpha| { + let push_size = if self.device.descriptor_buffer.is_some() { + size_of::() + } else { + size_of::() + }; + let info = PipelineCreateInfo { + format, + vert: self.rounded_fill_vert_shader.clone(), + frag: self.rounded_fill_frag_shader.clone(), + blend: src_has_alpha, + src_has_alpha, + has_alpha_mult: false, + alpha_mode: AlphaMode::PremultipliedOptical, + eotf: EOTF_LINEAR, + inv_eotf: EOTF_LINEAR, + descriptor_set_layouts: Default::default(), + has_color_management_data: false, + }; + self.device.create_pipeline2(info, push_size) + }; + let pipelines = Rc::new(static_map! { + TexSourceType::HasAlpha => create_pipeline(true)?, + TexSourceType::Opaque => create_pipeline(false)?, + }); + self.rounded_fill_pipelines.set(format, pipelines.clone()); + Ok(pipelines) + } + + pub(super) fn get_or_create_rounded_tex_pipelines( + &self, + format: vk::Format, + target_cd: &ColorDescription, + ) -> Rc { + let eotf = target_cd.eotf.to_vulkan(); + let pipelines = &self.rounded_tex_pipelines[eotf]; + match pipelines.get(&format) { + Some(pl) => pl, + _ => { + let pl = Rc::new(TexPipelines { + format, + eotf, + pipelines: Default::default(), + }); + pipelines.set(format, pl.clone()); + pl + } + } + } + + pub(super) fn get_or_create_rounded_tex_pipeline( + &self, + pipelines: &TexPipelines, + tex_cd: &ColorDescription, + tex_copy_type: TexCopyType, + tex_source_type: TexSourceType, + mut tex_alpha_mode: AlphaMode, + has_color_management_data: bool, + ) -> Result, VulkanError> { + if tex_source_type == TexSourceType::Opaque { + tex_alpha_mode = AlphaMode::PremultipliedElectrical; + } + let key = TexPipelineKey { + tex_copy_type, + tex_source_type, + tex_alpha_mode, + eotf: tex_cd.eotf.to_vulkan(), + has_color_management_data, + }; + if let Some(pl) = pipelines.pipelines.get(&key) { + return Ok(pl); + } + let has_alpha_mult = match tex_copy_type { + TexCopyType::Identity => false, + TexCopyType::Multiply => true, + }; + let push_size = if self.device.descriptor_buffer.is_some() { + size_of::() + } else { + size_of::() + }; + let info = PipelineCreateInfo { + format: pipelines.format, + vert: self.rounded_tex_vert_shader.clone(), + frag: self.rounded_tex_frag_shader.clone(), + blend: true, + src_has_alpha: true, + has_alpha_mult, + alpha_mode: key.tex_alpha_mode, + eotf: key.eotf.to_vulkan(), + inv_eotf: pipelines.eotf.to_vulkan(), + descriptor_set_layouts: self.tex_descriptor_set_layouts.clone(), + has_color_management_data, + }; + let pl = self.device.create_pipeline2(info, push_size)?; + pipelines.pipelines.set(key, pl.clone()); + Ok(pl) + } + + pub(super) fn get_or_create_tex_pipelines( + &self, + format: vk::Format, + target_cd: &ColorDescription, + ) -> Rc { + let eotf = target_cd.eotf.to_vulkan(); + let pipelines = &self.tex_pipelines[eotf]; + match pipelines.get(&format) { + Some(pl) => pl, + _ => { + let pl = Rc::new(TexPipelines { + format, + eotf, + pipelines: Default::default(), + }); + pipelines.set(format, pl.clone()); + pl + } + } + } + + pub(super) fn get_or_create_tex_pipeline( + &self, + pipelines: &TexPipelines, + tex_cd: &ColorDescription, + tex_copy_type: TexCopyType, + tex_source_type: TexSourceType, + mut tex_alpha_mode: AlphaMode, + has_color_management_data: bool, + ) -> Result, VulkanError> { + if tex_source_type == TexSourceType::Opaque { + tex_alpha_mode = AlphaMode::PremultipliedElectrical; + } + let key = TexPipelineKey { + tex_copy_type, + tex_source_type, + tex_alpha_mode, + eotf: tex_cd.eotf.to_vulkan(), + has_color_management_data, + }; + if let Some(pl) = pipelines.pipelines.get(&key) { + return Ok(pl); + } + let src_has_alpha = match tex_source_type { + TexSourceType::Opaque => false, + TexSourceType::HasAlpha => true, + }; + let has_alpha_mult = match tex_copy_type { + TexCopyType::Identity => false, + TexCopyType::Multiply => true, + }; + let push_size = if self.device.descriptor_buffer.is_some() { + size_of::() + } else { + size_of::() + }; + let info = PipelineCreateInfo { + format: pipelines.format, + vert: self.tex_vert_shader.clone(), + frag: self.tex_frag_shader.clone(), + blend: src_has_alpha || has_alpha_mult, + src_has_alpha, + has_alpha_mult, + alpha_mode: key.tex_alpha_mode, + eotf: key.eotf.to_vulkan(), + inv_eotf: pipelines.eotf.to_vulkan(), + descriptor_set_layouts: self.tex_descriptor_set_layouts.clone(), + has_color_management_data, + }; + let pl = self.device.create_pipeline2(info, push_size)?; + pipelines.pipelines.set(key, pl.clone()); + Ok(pl) + } + + pub(super) fn get_or_create_out_pipeline( + &self, + format: vk::Format, + bb_cd: &ColorDescription, + fb_cd: &ColorDescription, + has_color_management_data: bool, + ) -> Result, VulkanError> { + let key = OutPipelineKey { + format, + eotf: bb_cd.eotf.to_vulkan(), + has_color_management_data, + }; + let fb_eotf = fb_cd.eotf.to_vulkan(); + let pipelines = &self.out_pipelines[fb_eotf]; + if let Some(pl) = pipelines.get(&key) { + return Ok(pl); + } + let mut descriptor_set_layouts = ArrayVec::new(); + descriptor_set_layouts.push(self.out_descriptor_set_layout.clone().unwrap()); + let out = self + .device + .create_pipeline::(PipelineCreateInfo { + format: key.format, + vert: self.out_vert_shader.clone().unwrap(), + frag: self.out_frag_shader.clone().unwrap(), + blend: false, + src_has_alpha: true, + has_alpha_mult: false, + alpha_mode: AlphaMode::PremultipliedElectrical, + eotf: key.eotf.to_vulkan(), + inv_eotf: fb_eotf.to_vulkan(), + descriptor_set_layouts, + has_color_management_data, + })?; + pipelines.set(key, out.clone()); + Ok(out) + } +}