1
0
Fork 0
forked from wry/wry

vulkan: implement all alpha modes

This commit is contained in:
Julian Orth 2026-02-21 14:10:59 +01:00
parent 69ca5d92e7
commit 56a6012a7c
12 changed files with 62 additions and 11 deletions

View file

@ -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,

View file

@ -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,
}
}
}

View file

@ -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<Rc<VulkanDescriptorSetLayout>, 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);

View file

@ -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<ColorDescription>,
@ -258,6 +259,7 @@ type FillPipelines = Rc<StaticMap<TexSourceType, Rc<VulkanPipeline>>>;
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<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,
};
@ -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);

View file

@ -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

View file

@ -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

View file

@ -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;
}

View file

@ -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