From b7f93b37a64cbd765a9579d225798e7a0eb39758 Mon Sep 17 00:00:00 2001 From: Julian Orth Date: Tue, 25 Feb 2025 14:52:43 +0100 Subject: [PATCH] vulkan: rewrite shaders in terms of eotf and oetf --- src/gfx_apis/vulkan.rs | 1 + src/gfx_apis/vulkan/pipeline.rs | 10 +++++---- src/gfx_apis/vulkan/renderer.rs | 15 +++++++++---- .../vulkan/shaders/frag_spec_const.glsl | 3 ++- src/gfx_apis/vulkan/shaders/out.frag | 9 +++++--- src/gfx_apis/vulkan/shaders/tex.frag | 5 +++-- .../vulkan/shaders/transfer_functions.glsl | 21 +++++++++++++++++++ src/gfx_apis/vulkan/transfer_functions.rs | 2 ++ 8 files changed, 52 insertions(+), 14 deletions(-) create mode 100644 src/gfx_apis/vulkan/transfer_functions.rs diff --git a/src/gfx_apis/vulkan.rs b/src/gfx_apis/vulkan.rs index 8a1e568d..befd77d2 100644 --- a/src/gfx_apis/vulkan.rs +++ b/src/gfx_apis/vulkan.rs @@ -17,6 +17,7 @@ mod shaders; mod shm_image; mod staging; mod transfer; +mod transfer_functions; use { crate::{ diff --git a/src/gfx_apis/vulkan/pipeline.rs b/src/gfx_apis/vulkan/pipeline.rs index f4a4e4f9..1679d47a 100644 --- a/src/gfx_apis/vulkan/pipeline.rs +++ b/src/gfx_apis/vulkan/pipeline.rs @@ -39,7 +39,8 @@ pub(super) struct PipelineCreateInfo { pub(super) blend: bool, pub(super) src_has_alpha: bool, pub(super) has_alpha_mult: bool, - pub(super) with_linear_output: bool, + pub(super) eotf: u32, + pub(super) oetf: u32, pub(super) frag_descriptor_set_layout: Option>, } @@ -77,8 +78,8 @@ impl VulkanDevice { }; let destroy_layout = OnDrop(|| unsafe { self.device.destroy_pipeline_layout(pipeline_layout, None) }); - let mut frag_spec_data = ArrayVec::<_, { 3 * 4 }>::new(); - let mut frag_spec_entries = ArrayVec::<_, 3>::new(); + let mut frag_spec_data = ArrayVec::<_, { 4 * 4 }>::new(); + let mut frag_spec_entries = ArrayVec::<_, 4>::new(); let mut frag_spec_entry = |data: &[u8]| { let entry = SpecializationMapEntry::default() .constant_id(frag_spec_entries.len() as _) @@ -89,7 +90,8 @@ impl VulkanDevice { }; frag_spec_entry(&(info.src_has_alpha as u32).to_ne_bytes()); frag_spec_entry(&(info.has_alpha_mult as u32).to_ne_bytes()); - frag_spec_entry(&(info.with_linear_output as u32).to_ne_bytes()); + frag_spec_entry(&info.eotf.to_ne_bytes()); + frag_spec_entry(&info.oetf.to_ne_bytes()); let frag_spec = SpecializationInfo::default() .map_entries(&frag_spec_entries) .data(&frag_spec_data); diff --git a/src/gfx_apis/vulkan/renderer.rs b/src/gfx_apis/vulkan/renderer.rs index 8fbe8255..5eb50f1d 100644 --- a/src/gfx_apis/vulkan/renderer.rs +++ b/src/gfx_apis/vulkan/renderer.rs @@ -26,6 +26,7 @@ use { LEGACY_TEX_FRAG, LEGACY_TEX_VERT, OUT_FRAG, OUT_VERT, OutPushConstants, TEX_FRAG, TEX_VERT, TexPushConstants, VulkanShader, }, + transfer_functions::{TF_LINEAR, TF_SRGB}, }, io_uring::IoUring, rect::{Rect, Region}, @@ -305,7 +306,10 @@ impl VulkanRenderer { format: vk::Format, pass: RenderPass, ) -> Result, VulkanError> { - let with_linear_output = pass == RenderPass::BlendBuffer; + let (eotf, oetf) = match pass { + RenderPass::BlendBuffer => (TF_SRGB, TF_LINEAR), + RenderPass::FrameBuffer => (TF_SRGB, TF_SRGB), + }; let pipelines = &self.pipelines[pass]; if let Some(pl) = pipelines.get(&format) { return Ok(pl); @@ -319,7 +323,8 @@ impl VulkanRenderer { blend: src_has_alpha, src_has_alpha, has_alpha_mult: false, - with_linear_output, + eotf, + oetf, frag_descriptor_set_layout: None, }) }; @@ -334,7 +339,8 @@ impl VulkanRenderer { blend: src_has_alpha || has_alpha_mult, src_has_alpha, has_alpha_mult, - with_linear_output, + eotf, + oetf, frag_descriptor_set_layout: Some(self.tex_descriptor_set_layout.clone()), }) }; @@ -847,7 +853,8 @@ impl VulkanRenderer { blend: false, src_has_alpha: true, has_alpha_mult: false, - with_linear_output: true, + eotf: TF_LINEAR, + oetf: TF_SRGB, frag_descriptor_set_layout: Some(layout.clone()), })?; e.insert(out.clone()); diff --git a/src/gfx_apis/vulkan/shaders/frag_spec_const.glsl b/src/gfx_apis/vulkan/shaders/frag_spec_const.glsl index 751b18bf..ada35281 100644 --- a/src/gfx_apis/vulkan/shaders/frag_spec_const.glsl +++ b/src/gfx_apis/vulkan/shaders/frag_spec_const.glsl @@ -3,6 +3,7 @@ layout(constant_id = 0) const bool src_has_alpha = false; layout(constant_id = 1) const bool has_alpha_multiplier = false; -layout(constant_id = 2) const bool color_management = false; +layout(constant_id = 2) const uint eotf = 0; +layout(constant_id = 3) const uint oetf = 0; #endif diff --git a/src/gfx_apis/vulkan/shaders/out.frag b/src/gfx_apis/vulkan/shaders/out.frag index 8401e5be..c832dee7 100644 --- a/src/gfx_apis/vulkan/shaders/out.frag +++ b/src/gfx_apis/vulkan/shaders/out.frag @@ -10,8 +10,11 @@ layout(location = 0) out vec4 out_color; void main() { vec4 c = texelFetch(in_color, ivec2(gl_FragCoord.xy), 0); - c.rgb /= mix(c.a, 1.0, c.a == 0.0); - c.rgb = oetf_srgb(c.rgb); - c.rgb *= c.a; + if (eotf != oetf) { + c.rgb /= mix(c.a, 1.0, c.a == 0.0); + c.rgb = apply_eotf(c.rgb); + c.rgb = apply_oetf(c.rgb); + c.rgb *= c.a; + } out_color = c; } diff --git a/src/gfx_apis/vulkan/shaders/tex.frag b/src/gfx_apis/vulkan/shaders/tex.frag index 9d9476fd..53f74e8c 100644 --- a/src/gfx_apis/vulkan/shaders/tex.frag +++ b/src/gfx_apis/vulkan/shaders/tex.frag @@ -10,11 +10,12 @@ layout(location = 0) out vec4 out_color; void main() { vec4 c = textureLod(tex, tex_pos, 0); - if (color_management) { + if (eotf != oetf) { if (src_has_alpha) { c.rgb /= mix(c.a, 1.0, c.a == 0.0); } - c.rgb = eotf_srgb(c.rgb); + c.rgb = apply_eotf(c.rgb); + c.rgb = apply_oetf(c.rgb); if (src_has_alpha) { c.rgb *= c.a; } diff --git a/src/gfx_apis/vulkan/shaders/transfer_functions.glsl b/src/gfx_apis/vulkan/shaders/transfer_functions.glsl index d72332a0..d051d13d 100644 --- a/src/gfx_apis/vulkan/shaders/transfer_functions.glsl +++ b/src/gfx_apis/vulkan/shaders/transfer_functions.glsl @@ -1,6 +1,11 @@ #ifndef TRANSFER_FUNCTIONS_GLSL #define TRANSFER_FUNCTIONS_GLSL +#include "frag_spec_const.glsl" + +#define SRGB 0 +#define LINEAR 1 + vec3 eotf_srgb(vec3 c) { return mix( c * vec3(1.0 / 12.92), @@ -18,4 +23,20 @@ vec3 oetf_srgb(vec3 c) { ); } +vec3 apply_eotf(vec3 c) { + switch (eotf) { + case SRGB: return eotf_srgb(c); + case LINEAR: return c; + default: return c; + } +} + +vec3 apply_oetf(vec3 c) { + switch (oetf) { + case SRGB: return oetf_srgb(c); + case LINEAR: return c; + default: return c; + } +} + #endif diff --git a/src/gfx_apis/vulkan/transfer_functions.rs b/src/gfx_apis/vulkan/transfer_functions.rs new file mode 100644 index 00000000..b267ce1b --- /dev/null +++ b/src/gfx_apis/vulkan/transfer_functions.rs @@ -0,0 +1,2 @@ +pub const TF_SRGB: u32 = 0; +pub const TF_LINEAR: u32 = 1;