1
0
Fork 0
forked from wry/wry

vulkan: split renderer pipelines

This commit is contained in:
kossLAN 2026-05-29 21:35:40 -04:00
parent ea7251d6e0
commit 9437a56807
No known key found for this signature in database
2 changed files with 289 additions and 261 deletions

View file

@ -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<FillPipelines, VulkanError> {
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::<FillPushConstants>()
} else {
size_of::<LegacyFillPushConstants>()
};
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<FillPipelines, VulkanError> {
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::<RoundedFillPushConstants>()
} else {
size_of::<LegacyRoundedFillPushConstants>()
};
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<TexPipelines> {
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<Rc<VulkanPipeline>, 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::<RoundedTexPushConstants>()
} else {
size_of::<LegacyRoundedTexPushConstants>()
};
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<TexPipelines> {
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<Rc<VulkanPipeline>, 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::<TexPushConstants>()
} else {
size_of::<LegacyTexPushConstants>()
};
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<Rc<VulkanPipeline>, 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::<OutPushConstants>(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
}

View file

@ -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<FillPipelines, VulkanError> {
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::<FillPushConstants>()
} else {
size_of::<LegacyFillPushConstants>()
};
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<FillPipelines, VulkanError> {
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::<RoundedFillPushConstants>()
} else {
size_of::<LegacyRoundedFillPushConstants>()
};
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<TexPipelines> {
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<Rc<VulkanPipeline>, 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::<RoundedTexPushConstants>()
} else {
size_of::<LegacyRoundedTexPushConstants>()
};
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<TexPipelines> {
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<Rc<VulkanPipeline>, 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::<TexPushConstants>()
} else {
size_of::<LegacyTexPushConstants>()
};
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<Rc<VulkanPipeline>, 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::<OutPushConstants>(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)
}
}