1
0
Fork 0
forked from wry/wry

vulkan: support blend buffers having different primaries than framebuffer

This commit is contained in:
Julian Orth 2025-09-05 18:14:00 +02:00
parent 83e79b68e6
commit f475584f71
4 changed files with 73 additions and 37 deletions

View file

@ -120,33 +120,6 @@ impl VulkanDevice {
}))
}
pub(super) fn create_out_descriptor_set_layout(
self: &Rc<Self>,
db: &descriptor_buffer::Device,
) -> Result<Rc<VulkanDescriptorSetLayout>, VulkanError> {
let binding = DescriptorSetLayoutBinding::default()
.stage_flags(ShaderStageFlags::FRAGMENT)
.descriptor_count(1)
.descriptor_type(DescriptorType::SAMPLED_IMAGE);
let create_info = DescriptorSetLayoutCreateInfo::default()
.bindings(slice::from_ref(&binding))
.flags(DescriptorSetLayoutCreateFlags::DESCRIPTOR_BUFFER_EXT);
let layout = unsafe { self.device.create_descriptor_set_layout(&create_info, None) };
let layout = layout.map_err(VulkanError::CreateDescriptorSetLayout)?;
let size = self.get_descriptor_set_size(db, layout);
let mut offsets = ArrayVec::new();
unsafe {
offsets.push(db.get_descriptor_set_layout_binding_offset(layout, 0));
}
Ok(Rc::new(VulkanDescriptorSetLayout {
device: self.clone(),
layout,
size,
offsets,
_sampler: None,
}))
}
fn get_descriptor_set_size(
&self,
db: &descriptor_buffer::Device,

View file

@ -28,8 +28,8 @@ use {
shaders::{
FILL_FRAG, FILL_VERT, FillPushConstants, LEGACY_FILL_FRAG, LEGACY_FILL_VERT,
LEGACY_TEX_FRAG, LEGACY_TEX_VERT, LegacyFillPushConstants, LegacyTexPushConstants,
OUT_FRAG, OUT_VERT, OutPushConstants, TEX_FRAG, TEX_VERT, TexColorManagementData,
TexPushConstants, TexVertex, VulkanShader,
OUT_FRAG, OUT_VERT, OutColorManagementData, OutPushConstants, TEX_FRAG, TEX_VERT,
TexColorManagementData, TexPushConstants, TexVertex, VulkanShader,
},
},
io_uring::IoUring,
@ -179,6 +179,7 @@ pub(super) struct Memory {
uniform_buffer_writer: GenericBufferWriter,
uniform_buffer_descriptor_cache: Option<Box<[u8]>>,
blend_buffer_descriptor_buffer_offset: DeviceAddress,
blend_buffer_color_management_data_address: Option<DeviceSize>,
}
type Point = [[f32; 2]; 4];
@ -298,7 +299,7 @@ impl VulkanDevice {
let out_descriptor_set_layout = self
.descriptor_buffer
.as_ref()
.map(|db| self.create_out_descriptor_set_layout(db))
.map(|_| self.create_tex_resource_descriptor_set_layout())
.transpose()?;
let gfx_command_buffers = self.create_command_pool(self.graphics_queue_idx)?;
let transfer_command_buffers = self
@ -502,6 +503,7 @@ impl VulkanRenderer {
format: vk::Format,
bb_cd: &ColorDescription,
fb_cd: &ColorDescription,
has_color_management_data: bool,
) -> Result<Rc<VulkanPipeline>, VulkanError> {
let key = OutPipelineKey {
format,
@ -525,7 +527,7 @@ impl VulkanRenderer {
eotf: key.eotf.to_vulkan(),
inv_eotf: fb_cd.eotf.to_vulkan(),
descriptor_set_layouts,
has_color_management_data: false,
has_color_management_data,
})?;
pipelines.set(key, out.clone());
Ok(out)
@ -566,6 +568,20 @@ impl VulkanRenderer {
memory.blend_buffer_descriptor_buffer_offset = resource_writer.next_offset();
let mut writer = resource_writer.add_set(layout);
writer.write(layout.offsets[0], &bb.sampled_image_descriptor);
if let Some(addr) = memory.blend_buffer_color_management_data_address {
let uniform_buffer = DescriptorAddressInfoEXT::default()
.address(addr)
.range(size_of::<OutColorManagementData>() as _);
let info = DescriptorGetInfoEXT::default()
.ty(DescriptorType::UNIFORM_BUFFER)
.data(DescriptorDataEXT {
p_uniform_buffer: &uniform_buffer,
});
unsafe {
db.get_descriptor(&info, uniform_buffer_descriptor_cache);
}
writer.write(layout.offsets[1], uniform_buffer_descriptor_cache);
}
}
let tex_descriptor_set_layout = &self.tex_descriptor_set_layouts[1];
for pass in RenderPass::variants() {
@ -816,6 +832,26 @@ impl VulkanRenderer {
Ok(())
}
fn create_blend_cm_data(
&self,
bb: Option<&VulkanImage>,
bb_cd: &ColorDescription,
fb_cd: &ColorDescription,
) {
zone!("create_blend_cm_data");
let memory = &mut *self.memory.borrow_mut();
memory.blend_buffer_color_management_data_address = None;
if bb.is_none() {
return;
}
memory.blend_buffer_color_management_data_address = memory.color_transforms.get_offset(
&bb_cd.linear,
fb_cd,
self.device.uniform_buffer_offset_mask,
&mut memory.uniform_buffer_writer,
);
}
fn create_data_buffer(&self) -> Result<(), VulkanError> {
if self.device.descriptor_buffer.is_none() {
return Ok(());
@ -881,6 +917,9 @@ impl VulkanRenderer {
}
}
}
if let Some(addr) = &mut memory.blend_buffer_color_management_data_address {
*addr += buffer.buffer.address;
}
memory.used_buffers.push(buffer);
Ok(())
}
@ -1297,7 +1336,12 @@ impl VulkanRenderer {
zone!("blend_buffer_copy");
let memory = &*self.memory.borrow();
let db = self.device.descriptor_buffer.as_ref().unwrap();
let pipeline = self.get_or_create_out_pipeline(fb.format.vk_format, bb_cd, fb_cd)?;
let pipeline = self.get_or_create_out_pipeline(
fb.format.vk_format,
bb_cd,
fb_cd,
memory.blend_buffer_color_management_data_address.is_some(),
)?;
let push = OutPushConstants {
vertices: memory.out_address,
};
@ -1879,6 +1923,7 @@ impl VulkanRenderer {
let bb = blend_buffer.as_deref();
let buf = self.gfx_command_buffers.allocate()?;
self.convert_ops(opts, bb_cd, fb_cd)?;
self.create_blend_cm_data(bb, bb_cd, fb_cd);
self.create_data_buffer()?;
self.create_uniform_buffer()?;
self.collect_memory();

View file

@ -69,6 +69,14 @@ pub struct TexColorManagementData {
unsafe impl Packed for TexColorManagementData {}
#[derive(Copy, Clone, Debug)]
#[repr(C, align(16))]
pub struct OutColorManagementData {
pub matrix: [[f32; 4]; 4],
}
unsafe impl Packed for OutColorManagementData {}
#[derive(Copy, Clone, Debug)]
#[repr(C)]
pub struct LegacyTexPushConstants {

View file

@ -1,20 +1,30 @@
#version 450
#extension GL_EXT_samplerless_texture_functions : require
#extension GL_EXT_scalar_block_layout : require
#include "frag_spec_const.glsl"
#include "eotfs.glsl"
#include "out.common.glsl"
layout(set = 0, binding = 0) uniform texture2D in_color;
layout(set = 0, binding = 1, row_major, std430) uniform ColorManagementData {
mat4x4 matrix;
} cm_data;
layout(location = 0) out vec4 out_color;
void main() {
vec4 c = texelFetch(in_color, ivec2(gl_FragCoord.xy), 0);
if (eotf != inv_eotf) {
c.rgb /= mix(c.a, 1.0, c.a == 0.0);
c.rgb = apply_eotf(c.rgb);
c.rgb = apply_inv_eotf(c.rgb);
c.rgb *= c.a;
if (eotf != inv_eotf || has_matrix) {
vec3 rgb = c.rgb;
rgb /= mix(c.a, 1.0, c.a == 0.0);
rgb = apply_eotf(rgb);
if (has_matrix) {
rgb = (cm_data.matrix * vec4(rgb, 1.0)).rgb;
}
rgb = apply_inv_eotf(rgb);
rgb *= c.a;
c.rgb = rgb;
}
out_color = c;
}