vulkan: apply color space transforms to colors
This commit is contained in:
parent
b5044d7fe7
commit
c4d0fdd4bb
4 changed files with 73 additions and 13 deletions
|
|
@ -52,7 +52,6 @@ pub struct ColorDescription {
|
|||
}
|
||||
|
||||
impl LinearColorDescription {
|
||||
#[expect(dead_code)]
|
||||
pub fn color_transform(&self, target: &Self) -> ColorMatrix {
|
||||
let mut mat = target.local_from_xyz;
|
||||
if self.luminance != target.luminance {
|
||||
|
|
|
|||
|
|
@ -196,7 +196,6 @@ pub struct FillRect {
|
|||
pub rect: FramebufferRect,
|
||||
pub color: Color,
|
||||
pub alpha: Option<f32>,
|
||||
#[expect(dead_code)]
|
||||
pub cd: Rc<LinearColorDescription>,
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -556,7 +556,7 @@ impl GfxFramebuffer for VulkanImage {
|
|||
cd: &Rc<ColorDescription>,
|
||||
ops: &[GfxApiOpt],
|
||||
clear: Option<&Color>,
|
||||
_clear_cd: &Rc<LinearColorDescription>,
|
||||
clear_cd: &Rc<LinearColorDescription>,
|
||||
region: &Region,
|
||||
blend_buffer: Option<&Rc<dyn GfxBlendBuffer>>,
|
||||
blend_cd: &Rc<ColorDescription>,
|
||||
|
|
@ -581,6 +581,7 @@ impl GfxFramebuffer for VulkanImage {
|
|||
cd,
|
||||
ops,
|
||||
clear,
|
||||
clear_cd,
|
||||
region,
|
||||
blend_buffer,
|
||||
blend_cd,
|
||||
|
|
|
|||
|
|
@ -1,7 +1,11 @@
|
|||
use {
|
||||
crate::{
|
||||
async_engine::{AsyncEngine, SpawnedFuture},
|
||||
cmm::{cmm_description::ColorDescription, cmm_transfer_function::TransferFunction},
|
||||
cmm::{
|
||||
cmm_description::{ColorDescription, LinearColorDescription, LinearColorDescriptionId},
|
||||
cmm_transfer_function::TransferFunction,
|
||||
cmm_transform::ColorMatrix,
|
||||
},
|
||||
cpu_worker::PendingJob,
|
||||
gfx_api::{
|
||||
AcquireSync, BufferResv, BufferResvUser, GfxApiOpt, GfxBlendBuffer, GfxFormat,
|
||||
|
|
@ -57,6 +61,7 @@ use {
|
|||
std::{
|
||||
borrow::Cow,
|
||||
cell::{Cell, RefCell},
|
||||
collections::hash_map::Entry,
|
||||
fmt::{Debug, Formatter},
|
||||
mem,
|
||||
ops::Range,
|
||||
|
|
@ -169,6 +174,7 @@ pub(super) struct Memory {
|
|||
tex_targets: Vec<[Point; 2]>,
|
||||
data_buffer: Vec<u8>,
|
||||
out_address: DeviceAddress,
|
||||
color_transforms: ColorTransforms,
|
||||
}
|
||||
|
||||
type Point = [[f32; 2]; 4];
|
||||
|
|
@ -601,6 +607,7 @@ impl VulkanRenderer {
|
|||
memory.tex_targets.clear();
|
||||
memory.fill_targets.clear();
|
||||
memory.data_buffer.clear();
|
||||
memory.color_transforms.map.clear();
|
||||
let sync = |memory: &mut Memory| {
|
||||
for pass in RenderPass::variants() {
|
||||
let ops = &mut memory.ops_tmp[pass];
|
||||
|
|
@ -667,10 +674,6 @@ impl VulkanRenderer {
|
|||
if !bounds.intersects(&target) {
|
||||
continue;
|
||||
}
|
||||
let tf = match pass {
|
||||
RenderPass::BlendBuffer => blend_cd.transfer_function,
|
||||
RenderPass::FrameBuffer => fb_cd.transfer_function,
|
||||
};
|
||||
let ops = &mut memory.ops_tmp[pass];
|
||||
let lo = memory.fill_targets.len();
|
||||
for region in &memory.paint_regions[pass] {
|
||||
|
|
@ -684,7 +687,15 @@ impl VulkanRenderer {
|
|||
if lo == hi {
|
||||
continue;
|
||||
}
|
||||
let color = fr.color.to_array2(tf, fr.alpha);
|
||||
let target_cd = match pass {
|
||||
RenderPass::BlendBuffer => blend_cd,
|
||||
RenderPass::FrameBuffer => fb_cd,
|
||||
};
|
||||
let tf = target_cd.transfer_function;
|
||||
let color = memory
|
||||
.color_transforms
|
||||
.apply_to_color(&fr.cd, target_cd, fr.color);
|
||||
let color = color.to_array2(tf, fr.alpha);
|
||||
let source_type = match color[3] < 1.0 {
|
||||
false => TexSourceType::Opaque,
|
||||
true => TexSourceType::HasAlpha,
|
||||
|
|
@ -945,6 +956,7 @@ impl VulkanRenderer {
|
|||
buf: CommandBuffer,
|
||||
target: &VulkanImage,
|
||||
clear: Option<&Color>,
|
||||
clear_cd: &LinearColorDescription,
|
||||
pass: RenderPass,
|
||||
target_cd: &ColorDescription,
|
||||
) {
|
||||
|
|
@ -955,9 +967,12 @@ impl VulkanRenderer {
|
|||
let clear_rects = &memory.clear_rects[pass];
|
||||
if let Some(clear) = clear {
|
||||
if clear_rects.is_not_empty() {
|
||||
let color = memory
|
||||
.color_transforms
|
||||
.apply_to_color(clear_cd, target_cd, *clear);
|
||||
let clear_value = ClearValue {
|
||||
color: ClearColorValue {
|
||||
float32: clear.to_array(target_cd.transfer_function),
|
||||
float32: color.to_array(target_cd.transfer_function),
|
||||
},
|
||||
};
|
||||
let use_load_clear = clear_rects.len() == 1 && {
|
||||
|
|
@ -1599,6 +1614,7 @@ impl VulkanRenderer {
|
|||
fb_cd: &Rc<ColorDescription>,
|
||||
opts: &[GfxApiOpt],
|
||||
clear: Option<&Color>,
|
||||
clear_cd: &Rc<LinearColorDescription>,
|
||||
region: &Region,
|
||||
blend_buffer: Option<Rc<VulkanImage>>,
|
||||
blend_cd: &Rc<ColorDescription>,
|
||||
|
|
@ -1611,6 +1627,7 @@ impl VulkanRenderer {
|
|||
fb_cd,
|
||||
opts,
|
||||
clear,
|
||||
clear_cd,
|
||||
region,
|
||||
blend_buffer,
|
||||
blend_cd,
|
||||
|
|
@ -1779,6 +1796,7 @@ impl VulkanRenderer {
|
|||
fb_cd: &Rc<ColorDescription>,
|
||||
opts: &[GfxApiOpt],
|
||||
clear: Option<&Color>,
|
||||
clear_cd: &Rc<LinearColorDescription>,
|
||||
region: &Region,
|
||||
mut blend_buffer: Option<Rc<VulkanImage>>,
|
||||
bb_cd: &Rc<ColorDescription>,
|
||||
|
|
@ -1799,15 +1817,16 @@ impl VulkanRenderer {
|
|||
zone!("blend buffer pass");
|
||||
let rp = RenderPass::BlendBuffer;
|
||||
self.blend_buffer_initial_barrier(buf.buffer, bb);
|
||||
self.begin_rendering(buf.buffer, bb, clear, rp, bb_cd);
|
||||
self.begin_rendering(buf.buffer, bb, clear, clear_cd, rp, bb_cd);
|
||||
self.record_draws(buf.buffer, bb, rp, bb_cd)?;
|
||||
self.end_rendering(buf.buffer);
|
||||
self.blend_buffer_final_barrier(buf.buffer, bb);
|
||||
}
|
||||
{
|
||||
zone!("frame buffer pass");
|
||||
self.begin_rendering(buf.buffer, fb, clear, RenderPass::FrameBuffer, fb_cd);
|
||||
self.record_draws(buf.buffer, fb, RenderPass::FrameBuffer, fb_cd)?;
|
||||
let rp = RenderPass::FrameBuffer;
|
||||
self.begin_rendering(buf.buffer, fb, clear, clear_cd, rp, fb_cd);
|
||||
self.record_draws(buf.buffer, fb, rp, fb_cd)?;
|
||||
if let Some(bb) = bb {
|
||||
self.blend_buffer_copy(buf.buffer, fb, fb_cd, bb, bb_cd)?;
|
||||
}
|
||||
|
|
@ -2028,3 +2047,45 @@ where
|
|||
let y2 = y2.min(fb.height as i32);
|
||||
Some([x1, y1, x2, y2])
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
struct ColorTransforms {
|
||||
map: AHashMap<[LinearColorDescriptionId; 2], ColorTransform>,
|
||||
}
|
||||
|
||||
struct ColorTransform {
|
||||
matrix: ColorMatrix,
|
||||
}
|
||||
|
||||
impl ColorTransforms {
|
||||
fn get_or_create(
|
||||
&mut self,
|
||||
src: &LinearColorDescription,
|
||||
dst: &ColorDescription,
|
||||
) -> Option<&mut ColorTransform> {
|
||||
if src.id == dst.linear.id {
|
||||
return None;
|
||||
}
|
||||
let ct = match self.map.entry([src.id, dst.linear.id]) {
|
||||
Entry::Occupied(o) => o.into_mut(),
|
||||
Entry::Vacant(e) => {
|
||||
let matrix = src.color_transform(&dst.linear);
|
||||
let ct = ColorTransform { matrix };
|
||||
e.insert(ct)
|
||||
}
|
||||
};
|
||||
Some(ct)
|
||||
}
|
||||
|
||||
fn apply_to_color(
|
||||
&mut self,
|
||||
src: &LinearColorDescription,
|
||||
dst: &ColorDescription,
|
||||
mut color: Color,
|
||||
) -> Color {
|
||||
if let Some(ct) = self.get_or_create(src, dst) {
|
||||
color = ct.matrix * color;
|
||||
};
|
||||
color
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue