diff --git a/src/gfx_apis/vulkan.rs b/src/gfx_apis/vulkan.rs index ad0a5943..36662e47 100644 --- a/src/gfx_apis/vulkan.rs +++ b/src/gfx_apis/vulkan.rs @@ -1,4 +1,5 @@ mod allocator; +mod alpha_modes; mod blend_buffer; mod bo_allocator; mod buffer_cache; @@ -387,6 +388,10 @@ impl GfxContext for Context { self.0.device.descriptor_buffer.is_some() } + fn supports_alpha_modes(&self) -> bool { + self.0.device.descriptor_buffer.is_some() + } + fn create_dmabuf_buffer( &self, dmabuf: &OwnedFd, diff --git a/src/gfx_apis/vulkan/alpha_modes.rs b/src/gfx_apis/vulkan/alpha_modes.rs new file mode 100644 index 00000000..9480c2b0 --- /dev/null +++ b/src/gfx_apis/vulkan/alpha_modes.rs @@ -0,0 +1,15 @@ +use crate::gfx_api::AlphaMode; + +pub const AM_PREMULTIPLIED_ELECTRICAL: u32 = 0; +pub const AM_PREMULTIPLIED_OPTICAL: u32 = 1; +pub const AM_STRAIGHT: u32 = 2; + +impl AlphaMode { + pub fn to_vulkan(self) -> u32 { + match self { + AlphaMode::PremultipliedElectrical => AM_PREMULTIPLIED_ELECTRICAL, + AlphaMode::PremultipliedOptical => AM_PREMULTIPLIED_OPTICAL, + AlphaMode::Straight => AM_STRAIGHT, + } + } +} diff --git a/src/gfx_apis/vulkan/pipeline.rs b/src/gfx_apis/vulkan/pipeline.rs index 3e446eb2..5351a483 100644 --- a/src/gfx_apis/vulkan/pipeline.rs +++ b/src/gfx_apis/vulkan/pipeline.rs @@ -1,7 +1,10 @@ use { - crate::gfx_apis::vulkan::{ - VulkanError, descriptor::VulkanDescriptorSetLayout, device::VulkanDevice, - shaders::VulkanShader, + crate::{ + gfx_api::AlphaMode, + gfx_apis::vulkan::{ + VulkanError, descriptor::VulkanDescriptorSetLayout, device::VulkanDevice, + shaders::VulkanShader, + }, }, arrayvec::ArrayVec, ash::{ @@ -37,6 +40,7 @@ pub(super) struct PipelineCreateInfo { pub(super) blend: bool, pub(super) src_has_alpha: bool, pub(super) has_alpha_mult: bool, + pub(super) alpha_mode: AlphaMode, pub(super) eotf: u32, pub(super) inv_eotf: u32, pub(super) descriptor_set_layouts: ArrayVec, 2>, @@ -76,8 +80,8 @@ impl VulkanDevice { }; let destroy_layout = on_drop(|| unsafe { self.device.destroy_pipeline_layout(pipeline_layout, None) }); - let mut frag_spec_data = ArrayVec::<_, { 5 * 4 }>::new(); - let mut frag_spec_entries = ArrayVec::<_, 5>::new(); + let mut frag_spec_data = ArrayVec::<_, { 6 * 4 }>::new(); + let mut frag_spec_entries = ArrayVec::<_, 6>::new(); let mut frag_spec_entry = |data: &[u8]| { let entry = SpecializationMapEntry::default() .constant_id(frag_spec_entries.len() as _) @@ -91,6 +95,7 @@ impl VulkanDevice { frag_spec_entry(&info.eotf.to_ne_bytes()); frag_spec_entry(&info.inv_eotf.to_ne_bytes()); frag_spec_entry(&(info.has_color_management_data as u32).to_ne_bytes()); + frag_spec_entry(&info.alpha_mode.to_vulkan().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 29a983a2..44d11c2c 100644 --- a/src/gfx_apis/vulkan/renderer.rs +++ b/src/gfx_apis/vulkan/renderer.rs @@ -8,8 +8,8 @@ use { }, cpu_worker::PendingJob, gfx_api::{ - AcquireSync, BufferResv, BufferResvUser, GfxApiOpt, GfxBlendBuffer, GfxFormat, - GfxTexture, GfxWriteModifier, ReleaseSync, SyncFile, + AcquireSync, AlphaMode, BufferResv, BufferResvUser, GfxApiOpt, GfxBlendBuffer, + GfxFormat, GfxTexture, GfxWriteModifier, ReleaseSync, SyncFile, }, gfx_apis::vulkan::{ VulkanError, @@ -209,6 +209,7 @@ struct VulkanTexOp { alpha: f32, source_type: TexSourceType, copy_type: TexCopyType, + alpha_mode: AlphaMode, range_address: DeviceAddress, instances: u32, tex_cd: Rc, @@ -258,6 +259,7 @@ type FillPipelines = Rc>>; struct TexPipelineKey { tex_copy_type: TexCopyType, tex_source_type: TexSourceType, + tex_alpha_mode: AlphaMode, eotf: VulkanEotf, has_color_management_data: bool, } @@ -431,6 +433,7 @@ impl VulkanRenderer { 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, @@ -474,11 +477,16 @@ impl VulkanRenderer { 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, }; @@ -505,6 +513,7 @@ impl VulkanRenderer { 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(), @@ -543,6 +552,7 @@ impl VulkanRenderer { 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, @@ -886,6 +896,7 @@ impl VulkanRenderer { alpha: ct.alpha.unwrap_or_default(), source_type, copy_type, + alpha_mode: ct.alpha_mode, range_address: 0, instances: 0, tex_cd: ct.cd.clone(), @@ -1333,6 +1344,7 @@ impl VulkanRenderer { &c.tex_cd, c.copy_type, c.source_type, + c.alpha_mode, c.color_management_data_address.is_some(), )?; bind(&pipeline); diff --git a/src/gfx_apis/vulkan/shaders/alpha_modes.glsl b/src/gfx_apis/vulkan/shaders/alpha_modes.glsl new file mode 100644 index 00000000..1bb87a3e --- /dev/null +++ b/src/gfx_apis/vulkan/shaders/alpha_modes.glsl @@ -0,0 +1,8 @@ +#ifndef ALPHA_MODES_GLSL +#define ALPHA_MODES_GLSL + +#define AM_PREMULTIPLIED_ELECTRICAL 0 +#define AM_PREMULTIPLIED_OPTICAL 1 +#define AM_STRAIGHT 2 + +#endif diff --git a/src/gfx_apis/vulkan/shaders/frag_spec_const.glsl b/src/gfx_apis/vulkan/shaders/frag_spec_const.glsl index cf7f8a7c..29e3b2ef 100644 --- a/src/gfx_apis/vulkan/shaders/frag_spec_const.glsl +++ b/src/gfx_apis/vulkan/shaders/frag_spec_const.glsl @@ -6,5 +6,6 @@ layout(constant_id = 1) const bool has_alpha_multiplier = false; layout(constant_id = 2) const uint eotf = 0; layout(constant_id = 3) const uint inv_eotf = 0; layout(constant_id = 4) const bool has_matrix = false; +layout(constant_id = 5) const uint alpha_mode = 0; #endif diff --git a/src/gfx_apis/vulkan/shaders/tex.frag b/src/gfx_apis/vulkan/shaders/tex.frag index df6ee5ec..e1ccacda 100644 --- a/src/gfx_apis/vulkan/shaders/tex.frag +++ b/src/gfx_apis/vulkan/shaders/tex.frag @@ -8,6 +8,7 @@ #include "tex.common.glsl" #include "tex_set.glsl" #include "eotfs.glsl" +#include "alpha_modes.glsl" layout(set = 0, binding = 0) uniform sampler sam; layout(location = 0) in vec2 tex_pos; @@ -15,12 +16,15 @@ layout(location = 0) out vec4 out_color; void main() { vec4 c = textureLod(sampler2D(tex, sam), tex_pos, 0); - if (eotf != inv_eotf || has_matrix) { + if (eotf != inv_eotf || has_matrix || alpha_mode != AM_PREMULTIPLIED_ELECTRICAL) { vec3 rgb = c.rgb; - if (src_has_alpha) { + if (src_has_alpha && alpha_mode == AM_PREMULTIPLIED_ELECTRICAL) { rgb /= mix(c.a, 1.0, c.a == 0.0); } rgb = apply_eotf(rgb); + if (src_has_alpha && alpha_mode == AM_PREMULTIPLIED_OPTICAL) { + rgb /= mix(c.a, 1.0, c.a == 0.0); + } if (has_matrix) { rgb = (cm_data.matrix * vec4(rgb, 1.0)).rgb; } diff --git a/src/gfx_apis/vulkan/shaders_bin/legacy_fill.frag.spv b/src/gfx_apis/vulkan/shaders_bin/legacy_fill.frag.spv index 961877a7..b1377f0a 100644 Binary files a/src/gfx_apis/vulkan/shaders_bin/legacy_fill.frag.spv and b/src/gfx_apis/vulkan/shaders_bin/legacy_fill.frag.spv differ diff --git a/src/gfx_apis/vulkan/shaders_bin/legacy_tex.frag.spv b/src/gfx_apis/vulkan/shaders_bin/legacy_tex.frag.spv index 1c2f806f..9664f044 100644 Binary files a/src/gfx_apis/vulkan/shaders_bin/legacy_tex.frag.spv and b/src/gfx_apis/vulkan/shaders_bin/legacy_tex.frag.spv differ diff --git a/src/gfx_apis/vulkan/shaders_bin/out.frag.spv b/src/gfx_apis/vulkan/shaders_bin/out.frag.spv index d7421166..8490503a 100644 Binary files a/src/gfx_apis/vulkan/shaders_bin/out.frag.spv and b/src/gfx_apis/vulkan/shaders_bin/out.frag.spv differ diff --git a/src/gfx_apis/vulkan/shaders_bin/tex.frag.spv b/src/gfx_apis/vulkan/shaders_bin/tex.frag.spv index 6146efa8..c013804d 100644 Binary files a/src/gfx_apis/vulkan/shaders_bin/tex.frag.spv and b/src/gfx_apis/vulkan/shaders_bin/tex.frag.spv differ diff --git a/src/gfx_apis/vulkan/shaders_hash.txt b/src/gfx_apis/vulkan/shaders_hash.txt index 9d144084..ab855a2d 100644 --- a/src/gfx_apis/vulkan/shaders_hash.txt +++ b/src/gfx_apis/vulkan/shaders_hash.txt @@ -1,8 +1,9 @@ +302a9f250bdc4f8e0e71a9f77c9a8a7aa55fd003bc91c2422a700c4abd83f54e src/gfx_apis/vulkan/shaders/alpha_modes.glsl b6a0df1e231fab533499329636b7a580384784418baee06c147af5fcc384cf5c src/gfx_apis/vulkan/shaders/eotfs.glsl 8a38df18851cd13884499820f26939fb7319f45d913d867f254d8118d59fb117 src/gfx_apis/vulkan/shaders/fill.common.glsl 21c488d12aa5ad2f109ec44cb856dfe837e02ea9025b5ed64439d742c17cbf30 src/gfx_apis/vulkan/shaders/fill.frag 4fb481d8d73afdfb0d8f077eb8665d86f06c8a32a91e44ed369ef5dff554646d src/gfx_apis/vulkan/shaders/fill.vert -63af15c4e00587a7bb8494934c88d9874712a511217829b50f3c08fa3c461082 src/gfx_apis/vulkan/shaders/frag_spec_const.glsl +f93524fd077bc9984702b1e0f92232f80bfe28a0a92439dc164c1ea41fd16d64 src/gfx_apis/vulkan/shaders/frag_spec_const.glsl c315a064b48dd5bdb607a6b79c30d31b6e59ffec69e93d50ab875abf97c41bbf src/gfx_apis/vulkan/shaders/legacy/fill.common.glsl 590d061b97446fc501158609eaf098b71bc7b328c008b586ff36613ce690d618 src/gfx_apis/vulkan/shaders/legacy/fill.frag ad22a79e1a88a12daa40c0a2b953084c129a408297c8ca544d60e0b6001470b9 src/gfx_apis/vulkan/shaders/legacy/fill.vert @@ -13,6 +14,6 @@ e0a8769dd7938dd02e66db9e9048ed6bef8f8c42671f2e2c7a7976a6d498f685 src/gfx_apis/vu 5069f619c7d722815a022e2d84720a2d8290af49a3ed49ea0cd26b52115cc39a src/gfx_apis/vulkan/shaders/out.frag 0adc7e12328c15fb3e7e6c8b8701a182223c2f15337e14131f41dd247e697809 src/gfx_apis/vulkan/shaders/out.vert e22d4d3318a350def8ef19c7b27dc6a308a84c2fe9d7c02b81107f72073cd481 src/gfx_apis/vulkan/shaders/tex.common.glsl -06993d4d882fe5c651e5ab54f0116b9622352a97f3575985076ef464b472dd39 src/gfx_apis/vulkan/shaders/tex.frag +1f196cee646a934072beb3e5648a5042c035953d9a0c26b0a22e330c2f8bb994 src/gfx_apis/vulkan/shaders/tex.frag 423cf327c9fcc4070dbf75321c1224a1589b6cf3d2f1ea5e8bd0362e1a9f3aa1 src/gfx_apis/vulkan/shaders/tex.vert b982f7101c22931a33b32dce3408387f3392c0f0ad0ca5852da265b0d12856bb src/gfx_apis/vulkan/shaders/tex_set.glsl