vulkan: apply color space transforms to textures
This commit is contained in:
parent
c4d0fdd4bb
commit
8e65de91f9
12 changed files with 233 additions and 66 deletions
|
|
@ -157,7 +157,6 @@ impl<T, U> ColorMatrix<T, U> {
|
|||
Self(m, PhantomData)
|
||||
}
|
||||
|
||||
#[expect(dead_code)]
|
||||
pub const fn to_f32(&self) -> [[f32; 4]; 4] {
|
||||
let m = &self.0;
|
||||
macro_rules! map {
|
||||
|
|
|
|||
|
|
@ -106,8 +106,6 @@ impl VulkanRenderer {
|
|||
ty: VulkanImageMemory::Blend(allocation),
|
||||
bridge: None,
|
||||
sampled_image_descriptor: self.sampled_image_descriptor(view),
|
||||
descriptor_buffer_version: Default::default(),
|
||||
descriptor_buffer_offset: Default::default(),
|
||||
execution_version: Default::default(),
|
||||
});
|
||||
cached.insert_entry(Rc::downgrade(&img));
|
||||
|
|
|
|||
|
|
@ -12,7 +12,8 @@ use {
|
|||
DeviceSize,
|
||||
},
|
||||
gpu_alloc::UsageFlags,
|
||||
std::{cell::RefCell, mem::ManuallyDrop, rc::Rc},
|
||||
std::{cell::RefCell, mem::ManuallyDrop, ops::Deref, rc::Rc},
|
||||
uapi::Packed,
|
||||
};
|
||||
|
||||
pub struct VulkanBufferCache {
|
||||
|
|
@ -20,6 +21,7 @@ pub struct VulkanBufferCache {
|
|||
allocator: Rc<VulkanAllocator>,
|
||||
buffers: RefCell<Vec<VulkanBufferUnused>>,
|
||||
usage: BufferUsageFlags,
|
||||
min_alignment: DeviceSize,
|
||||
}
|
||||
|
||||
pub struct VulkanBuffer {
|
||||
|
|
@ -40,12 +42,14 @@ impl VulkanBufferCache {
|
|||
device: &Rc<VulkanDevice>,
|
||||
allocator: &Rc<VulkanAllocator>,
|
||||
usage: BufferUsageFlags,
|
||||
min_alignment: DeviceSize,
|
||||
) -> Rc<Self> {
|
||||
Rc::new(Self {
|
||||
device: device.clone(),
|
||||
allocator: allocator.clone(),
|
||||
buffers: Default::default(),
|
||||
usage,
|
||||
min_alignment,
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -55,25 +59,27 @@ impl VulkanBufferCache {
|
|||
for_sampler: bool,
|
||||
) -> Rc<Self> {
|
||||
let mut usage = BufferUsageFlags::SHADER_DEVICE_ADDRESS;
|
||||
let mut min_alignment = 1;
|
||||
if for_sampler {
|
||||
usage |= BufferUsageFlags::SAMPLER_DESCRIPTOR_BUFFER_EXT;
|
||||
} else {
|
||||
usage |= BufferUsageFlags::RESOURCE_DESCRIPTOR_BUFFER_EXT;
|
||||
if device.is_anv {
|
||||
// https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/33903
|
||||
min_alignment = 4096;
|
||||
}
|
||||
}
|
||||
Self::new(device, allocator, usage)
|
||||
Self::new(device, allocator, usage, min_alignment)
|
||||
}
|
||||
|
||||
pub fn usage(&self) -> BufferUsageFlags {
|
||||
self.usage
|
||||
}
|
||||
|
||||
pub fn allocate(
|
||||
self: &Rc<Self>,
|
||||
capacity: DeviceSize,
|
||||
align: DeviceSize,
|
||||
) -> Result<VulkanBuffer, VulkanError> {
|
||||
pub fn allocate(self: &Rc<Self>, capacity: DeviceSize) -> Result<VulkanBuffer, VulkanError> {
|
||||
const MIN_ALLOCATION: DeviceSize = 1024;
|
||||
let capacity = (capacity.max(MIN_ALLOCATION) + align - 1) & !(align - 1);
|
||||
let align_mask = self.min_alignment - 1;
|
||||
let capacity = (capacity.max(MIN_ALLOCATION) + align_mask) & !align_mask;
|
||||
let mut smallest = None;
|
||||
let mut smallest_size = DeviceSize::MAX;
|
||||
let mut fitting = None;
|
||||
|
|
@ -116,7 +122,7 @@ impl VulkanBufferCache {
|
|||
let destroy_buffer = OnDrop(|| unsafe { self.device.device.destroy_buffer(buffer, None) });
|
||||
let mut memory_requirements =
|
||||
unsafe { self.device.device.get_buffer_memory_requirements(buffer) };
|
||||
memory_requirements.alignment = memory_requirements.alignment.max(align);
|
||||
memory_requirements.alignment = memory_requirements.alignment.max(self.min_alignment);
|
||||
let allocation = {
|
||||
let flags = UsageFlags::UPLOAD
|
||||
| UsageFlags::FAST_DEVICE_ACCESS
|
||||
|
|
@ -162,3 +168,31 @@ impl Drop for VulkanBufferUnused {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct GenericBufferWriter {
|
||||
buf: Vec<u8>,
|
||||
}
|
||||
|
||||
impl GenericBufferWriter {
|
||||
pub fn clear(&mut self) {
|
||||
self.buf.clear();
|
||||
}
|
||||
|
||||
pub fn write(&mut self, offset_mask: DeviceSize, data: &(impl Packed + ?Sized)) -> DeviceSize {
|
||||
let mut offset = self.buf.len() as DeviceSize;
|
||||
let mask = offset_mask | (align_of_val(data) as DeviceSize - 1);
|
||||
offset = (offset + mask) & !mask;
|
||||
self.buf.resize(offset as usize, 0);
|
||||
self.buf.extend_from_slice(uapi::as_bytes(data));
|
||||
offset
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for GenericBufferWriter {
|
||||
type Target = [u8];
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.buf
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ pub(super) struct VulkanDescriptorSetLayout {
|
|||
pub(super) device: Rc<VulkanDevice>,
|
||||
pub(super) layout: DescriptorSetLayout,
|
||||
pub(super) size: DeviceSize,
|
||||
pub(super) offsets: ArrayVec<DeviceSize, 1>,
|
||||
pub(super) offsets: ArrayVec<DeviceSize, 2>,
|
||||
pub(super) _sampler: Option<Rc<VulkanSampler>>,
|
||||
}
|
||||
|
||||
|
|
@ -87,12 +87,20 @@ impl VulkanDevice {
|
|||
pub(super) fn create_tex_resource_descriptor_set_layout(
|
||||
self: &Rc<Self>,
|
||||
) -> Result<Rc<VulkanDescriptorSetLayout>, VulkanError> {
|
||||
let binding = DescriptorSetLayoutBinding::default()
|
||||
.stage_flags(ShaderStageFlags::FRAGMENT)
|
||||
.descriptor_count(1)
|
||||
.descriptor_type(DescriptorType::SAMPLED_IMAGE);
|
||||
let bindings = [
|
||||
DescriptorSetLayoutBinding::default()
|
||||
.binding(0)
|
||||
.stage_flags(ShaderStageFlags::FRAGMENT)
|
||||
.descriptor_count(1)
|
||||
.descriptor_type(DescriptorType::SAMPLED_IMAGE),
|
||||
DescriptorSetLayoutBinding::default()
|
||||
.binding(1)
|
||||
.stage_flags(ShaderStageFlags::FRAGMENT)
|
||||
.descriptor_count(1)
|
||||
.descriptor_type(DescriptorType::UNIFORM_BUFFER),
|
||||
];
|
||||
let create_info = DescriptorSetLayoutCreateInfo::default()
|
||||
.bindings(slice::from_ref(&binding))
|
||||
.bindings(&bindings)
|
||||
.flags(DescriptorSetLayoutCreateFlags::DESCRIPTOR_BUFFER_EXT);
|
||||
let layout = unsafe { self.device.create_descriptor_set_layout(&create_info, None) };
|
||||
let layout = layout.map_err(VulkanError::CreateDescriptorSetLayout)?;
|
||||
|
|
@ -101,6 +109,7 @@ impl VulkanDevice {
|
|||
let mut offsets = ArrayVec::new();
|
||||
unsafe {
|
||||
offsets.push(db.get_descriptor_set_layout_binding_offset(layout, 0));
|
||||
offsets.push(db.get_descriptor_set_layout_binding_offset(layout, 1));
|
||||
}
|
||||
Ok(Rc::new(VulkanDescriptorSetLayout {
|
||||
device: self.clone(),
|
||||
|
|
|
|||
|
|
@ -37,8 +37,9 @@ use {
|
|||
PhysicalDeviceDrmPropertiesEXT, PhysicalDeviceDynamicRenderingFeatures,
|
||||
PhysicalDeviceExternalSemaphoreInfo, PhysicalDeviceProperties,
|
||||
PhysicalDeviceProperties2, PhysicalDeviceSynchronization2Features,
|
||||
PhysicalDeviceTimelineSemaphoreFeatures, PhysicalDeviceVulkan12Properties, Queue,
|
||||
QueueFlags,
|
||||
PhysicalDeviceTimelineSemaphoreFeatures,
|
||||
PhysicalDeviceUniformBufferStandardLayoutFeatures, PhysicalDeviceVulkan12Properties,
|
||||
Queue, QueueFlags,
|
||||
},
|
||||
},
|
||||
isnt::std_1::collections::IsntHashMap2Ext,
|
||||
|
|
@ -75,6 +76,8 @@ pub struct VulkanDevice {
|
|||
pub(super) sampler_descriptor_size: usize,
|
||||
pub(super) sampled_image_descriptor_size: usize,
|
||||
pub(super) is_anv: bool,
|
||||
pub(super) uniform_buffer_offset_mask: DeviceSize,
|
||||
pub(super) uniform_buffer_descriptor_size: usize,
|
||||
}
|
||||
|
||||
impl Drop for VulkanDevice {
|
||||
|
|
@ -308,6 +311,9 @@ impl VulkanInstance {
|
|||
PhysicalDeviceDescriptorBufferFeaturesEXT::default().descriptor_buffer(true);
|
||||
let mut buffer_device_address_features =
|
||||
PhysicalDeviceBufferDeviceAddressFeatures::default().buffer_device_address(true);
|
||||
let mut uniform_buffer_standard_layout_features =
|
||||
PhysicalDeviceUniformBufferStandardLayoutFeatures::default()
|
||||
.uniform_buffer_standard_layout(true);
|
||||
let mut queue_create_infos = ArrayVec::<_, 2>::new();
|
||||
queue_create_infos.push(
|
||||
DeviceQueueCreateInfo::default()
|
||||
|
|
@ -325,6 +331,7 @@ impl VulkanInstance {
|
|||
.push_next(&mut semaphore_features)
|
||||
.push_next(&mut synchronization2_features)
|
||||
.push_next(&mut dynamic_rendering_features)
|
||||
.push_next(&mut uniform_buffer_standard_layout_features)
|
||||
.queue_create_infos(&queue_create_infos)
|
||||
.enabled_extension_names(&enabled_extensions);
|
||||
if supports_descriptor_buffer {
|
||||
|
|
@ -382,6 +389,14 @@ impl VulkanInstance {
|
|||
let mut descriptor_buffer_offset_mask = 0;
|
||||
let mut sampler_descriptor_size = 0;
|
||||
let mut sampled_image_descriptor_size = 0;
|
||||
let mut uniform_buffer_descriptor_size = 0;
|
||||
let uniform_buffer_offset_mask = physical_device_properties2
|
||||
.properties
|
||||
.limits
|
||||
.min_uniform_buffer_offset_alignment
|
||||
.checked_next_power_of_two()
|
||||
.unwrap()
|
||||
- 1;
|
||||
if supports_descriptor_buffer {
|
||||
descriptor_buffer_offset_mask = descriptor_buffer_props
|
||||
.descriptor_buffer_offset_alignment
|
||||
|
|
@ -390,6 +405,7 @@ impl VulkanInstance {
|
|||
- 1;
|
||||
sampler_descriptor_size = descriptor_buffer_props.sampler_descriptor_size;
|
||||
sampled_image_descriptor_size = descriptor_buffer_props.sampled_image_descriptor_size;
|
||||
uniform_buffer_descriptor_size = descriptor_buffer_props.uniform_buffer_descriptor_size;
|
||||
}
|
||||
let memory_properties =
|
||||
unsafe { self.instance.get_physical_device_memory_properties(phy_dev) };
|
||||
|
|
@ -432,6 +448,8 @@ impl VulkanInstance {
|
|||
blend_limits,
|
||||
is_anv: physical_device_vulkan12_properties.driver_id
|
||||
== DriverId::INTEL_OPEN_SOURCE_MESA,
|
||||
uniform_buffer_offset_mask,
|
||||
uniform_buffer_descriptor_size,
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,8 +21,8 @@ use {
|
|||
ash::vk::{
|
||||
BindImageMemoryInfo, BindImagePlaneMemoryInfo, ComponentMapping, ComponentSwizzle,
|
||||
DescriptorDataEXT, DescriptorGetInfoEXT, DescriptorImageInfo, DescriptorType, DeviceMemory,
|
||||
DeviceSize, Extent3D, ExternalMemoryHandleTypeFlags, ExternalMemoryImageCreateInfo,
|
||||
FormatFeatureFlags, Image, ImageAspectFlags, ImageCreateFlags, ImageCreateInfo,
|
||||
Extent3D, ExternalMemoryHandleTypeFlags, ExternalMemoryImageCreateInfo, FormatFeatureFlags,
|
||||
Image, ImageAspectFlags, ImageCreateFlags, ImageCreateInfo,
|
||||
ImageDrmFormatModifierExplicitCreateInfoEXT, ImageLayout, ImageMemoryRequirementsInfo2,
|
||||
ImagePlaneMemoryRequirementsInfo, ImageSubresourceRange, ImageTiling, ImageType,
|
||||
ImageUsageFlags, ImageView, ImageViewCreateInfo, ImageViewType, ImportMemoryFdInfoKHR,
|
||||
|
|
@ -66,8 +66,6 @@ pub struct VulkanImage {
|
|||
pub(super) ty: VulkanImageMemory,
|
||||
pub(super) bridge: Option<VulkanFramebufferBridge>,
|
||||
pub(super) sampled_image_descriptor: Box<[u8]>,
|
||||
pub(super) descriptor_buffer_version: Cell<u64>,
|
||||
pub(super) descriptor_buffer_offset: Cell<DeviceSize>,
|
||||
pub(super) execution_version: Cell<u64>,
|
||||
}
|
||||
|
||||
|
|
@ -468,8 +466,6 @@ impl VulkanDmaBufImageTemplate {
|
|||
}),
|
||||
bridge,
|
||||
sampled_image_descriptor: self.renderer.sampled_image_descriptor(texture_view),
|
||||
descriptor_buffer_version: Cell::new(0),
|
||||
descriptor_buffer_offset: Cell::new(0),
|
||||
execution_version: Cell::new(0),
|
||||
}))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ pub(super) struct PipelineCreateInfo {
|
|||
pub(super) eotf: u32,
|
||||
pub(super) oetf: u32,
|
||||
pub(super) descriptor_set_layouts: ArrayVec<Rc<VulkanDescriptorSetLayout>, 2>,
|
||||
pub(super) has_color_management_data: bool,
|
||||
}
|
||||
|
||||
impl VulkanDevice {
|
||||
|
|
@ -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::<_, { 4 * 4 }>::new();
|
||||
let mut frag_spec_entries = ArrayVec::<_, 4>::new();
|
||||
let mut frag_spec_data = ArrayVec::<_, { 5 * 4 }>::new();
|
||||
let mut frag_spec_entries = ArrayVec::<_, 5>::new();
|
||||
let mut frag_spec_entry = |data: &[u8]| {
|
||||
let entry = SpecializationMapEntry::default()
|
||||
.constant_id(frag_spec_entries.len() as _)
|
||||
|
|
@ -91,6 +92,7 @@ impl VulkanDevice {
|
|||
frag_spec_entry(&(info.has_alpha_mult as u32).to_ne_bytes());
|
||||
frag_spec_entry(&info.eotf.to_ne_bytes());
|
||||
frag_spec_entry(&info.oetf.to_ne_bytes());
|
||||
frag_spec_entry(&(info.has_color_management_data as u32).to_ne_bytes());
|
||||
let frag_spec = SpecializationInfo::default()
|
||||
.map_entries(&frag_spec_entries)
|
||||
.data(&frag_spec_data);
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ use {
|
|||
gfx_apis::vulkan::{
|
||||
VulkanError,
|
||||
allocator::{VulkanAllocator, VulkanThreadedAllocator},
|
||||
buffer_cache::{VulkanBuffer, VulkanBufferCache},
|
||||
buffer_cache::{GenericBufferWriter, VulkanBuffer, VulkanBufferCache},
|
||||
command::{VulkanCommandBuffer, VulkanCommandPool},
|
||||
descriptor::VulkanDescriptorSetLayout,
|
||||
descriptor_buffer::VulkanDescriptorBufferWriter,
|
||||
|
|
@ -27,8 +27,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, TexPushConstants,
|
||||
TexVertex, VulkanShader,
|
||||
OUT_FRAG, OUT_VERT, OutPushConstants, TEX_FRAG, TEX_VERT, TexColorManagementData,
|
||||
TexPushConstants, TexVertex, VulkanShader,
|
||||
},
|
||||
transfer_functions::{TF_LINEAR, TransferFunctionExt},
|
||||
},
|
||||
|
|
@ -46,9 +46,10 @@ use {
|
|||
self, AccessFlags2, AttachmentLoadOp, AttachmentStoreOp, BufferUsageFlags,
|
||||
ClearAttachment, ClearColorValue, ClearRect, ClearValue, CommandBuffer,
|
||||
CommandBufferBeginInfo, CommandBufferSubmitInfo, CommandBufferUsageFlags,
|
||||
CopyImageInfo2, DependencyInfoKHR, DescriptorBufferBindingInfoEXT, DescriptorImageInfo,
|
||||
DescriptorType, DeviceAddress, DeviceSize, Extent2D, Extent3D, ImageAspectFlags,
|
||||
ImageCopy2, ImageLayout, ImageMemoryBarrier2, ImageSubresourceLayers,
|
||||
CopyImageInfo2, DependencyInfoKHR, DescriptorAddressInfoEXT,
|
||||
DescriptorBufferBindingInfoEXT, DescriptorDataEXT, DescriptorGetInfoEXT,
|
||||
DescriptorImageInfo, DescriptorType, DeviceAddress, DeviceSize, Extent2D, Extent3D,
|
||||
ImageAspectFlags, ImageCopy2, ImageLayout, ImageMemoryBarrier2, ImageSubresourceLayers,
|
||||
ImageSubresourceRange, Offset2D, Offset3D, PipelineBindPoint, PipelineStageFlags2,
|
||||
QUEUE_FAMILY_FOREIGN_EXT, Rect2D, RenderingAttachmentInfo, RenderingInfo,
|
||||
SemaphoreSubmitInfo, SemaphoreSubmitInfoKHR, ShaderStageFlags, SubmitInfo2, Viewport,
|
||||
|
|
@ -108,6 +109,7 @@ pub struct VulkanRenderer {
|
|||
pub(super) resource_descriptor_buffer_cache: Rc<VulkanBufferCache>,
|
||||
pub(super) blend_buffers: RefCell<AHashMap<(u32, u32), Weak<VulkanImage>>>,
|
||||
pub(super) shader_buffer_cache: Rc<VulkanBufferCache>,
|
||||
pub(super) uniform_buffer_cache: Rc<VulkanBufferCache>,
|
||||
}
|
||||
|
||||
pub(super) struct CachedCommandBuffers {
|
||||
|
|
@ -159,7 +161,7 @@ pub(super) struct Memory {
|
|||
wait_semaphore_infos: Vec<SemaphoreSubmitInfo<'static>>,
|
||||
release_fence: Option<Rc<VulkanFence>>,
|
||||
release_sync_file: Option<SyncFile>,
|
||||
used_buffers: ArrayVec<VulkanBuffer, 3>,
|
||||
used_buffers: ArrayVec<VulkanBuffer, 4>,
|
||||
paint_bounds: StaticMap<RenderPass, Option<PaintRegion>>,
|
||||
paint_regions: StaticMap<RenderPass, Vec<PaintRegion>>,
|
||||
clear_rects: StaticMap<RenderPass, Vec<ClearRect>>,
|
||||
|
|
@ -175,6 +177,9 @@ pub(super) struct Memory {
|
|||
data_buffer: Vec<u8>,
|
||||
out_address: DeviceAddress,
|
||||
color_transforms: ColorTransforms,
|
||||
uniform_buffer_writer: GenericBufferWriter,
|
||||
uniform_buffer_descriptor_cache: Option<Box<[u8]>>,
|
||||
blend_buffer_descriptor_buffer_offset: DeviceAddress,
|
||||
}
|
||||
|
||||
type Point = [[f32; 2]; 4];
|
||||
|
|
@ -196,6 +201,8 @@ struct VulkanTexOp {
|
|||
range_address: DeviceAddress,
|
||||
instances: u32,
|
||||
tex_cd: Rc<ColorDescription>,
|
||||
color_management_data_address: Option<DeviceAddress>,
|
||||
resource_descriptor_buffer_offset: DeviceAddress,
|
||||
}
|
||||
|
||||
struct VulkanFillOp {
|
||||
|
|
@ -230,7 +237,7 @@ pub(super) struct PendingFrame {
|
|||
wait_semaphores: Cell<Vec<Rc<VulkanSemaphore>>>,
|
||||
waiter: Cell<Option<SpawnedFuture<()>>>,
|
||||
_release_fence: Option<Rc<VulkanFence>>,
|
||||
_used_buffers: ArrayVec<VulkanBuffer, 3>,
|
||||
_used_buffers: ArrayVec<VulkanBuffer, 4>,
|
||||
}
|
||||
|
||||
type FillPipelines = Rc<StaticMap<TexSourceType, Rc<VulkanPipeline>>>;
|
||||
|
|
@ -240,6 +247,7 @@ struct TexPipelineKey {
|
|||
tex_copy_type: TexCopyType,
|
||||
tex_source_type: TexSourceType,
|
||||
eotf: TransferFunction,
|
||||
has_color_management_data: bool,
|
||||
}
|
||||
|
||||
pub(super) struct TexPipelines {
|
||||
|
|
@ -338,7 +346,13 @@ impl VulkanDevice {
|
|||
let shader_buffer_cache = {
|
||||
// TODO: https://github.com/KhronosGroup/Vulkan-Samples/issues/1286
|
||||
let usage = BufferUsageFlags::SHADER_DEVICE_ADDRESS | BufferUsageFlags::STORAGE_BUFFER;
|
||||
VulkanBufferCache::new(self, &allocator, usage)
|
||||
let align = 8;
|
||||
VulkanBufferCache::new(self, &allocator, usage, align)
|
||||
};
|
||||
let uniform_buffer_cache = {
|
||||
let usage = BufferUsageFlags::SHADER_DEVICE_ADDRESS | BufferUsageFlags::UNIFORM_BUFFER;
|
||||
let align = align_of::<TexColorManagementData>() as DeviceSize;
|
||||
VulkanBufferCache::new(self, &allocator, usage, align)
|
||||
};
|
||||
let render = Rc::new(VulkanRenderer {
|
||||
formats: Rc::new(formats),
|
||||
|
|
@ -374,6 +388,7 @@ impl VulkanDevice {
|
|||
resource_descriptor_buffer_cache,
|
||||
blend_buffers: Default::default(),
|
||||
shader_buffer_cache,
|
||||
uniform_buffer_cache,
|
||||
});
|
||||
Ok(render)
|
||||
}
|
||||
|
|
@ -404,6 +419,7 @@ impl VulkanRenderer {
|
|||
eotf: TF_LINEAR,
|
||||
oetf: TF_LINEAR,
|
||||
descriptor_set_layouts: Default::default(),
|
||||
has_color_management_data: false,
|
||||
};
|
||||
self.device.create_pipeline2(info, push_size)
|
||||
};
|
||||
|
|
@ -441,11 +457,13 @@ impl VulkanRenderer {
|
|||
tex_cd: &ColorDescription,
|
||||
tex_copy_type: TexCopyType,
|
||||
tex_source_type: TexSourceType,
|
||||
has_color_management_data: bool,
|
||||
) -> Result<Rc<VulkanPipeline>, VulkanError> {
|
||||
let key = TexPipelineKey {
|
||||
tex_copy_type,
|
||||
tex_source_type,
|
||||
eotf: tex_cd.transfer_function,
|
||||
has_color_management_data,
|
||||
};
|
||||
if let Some(pl) = pipelines.pipelines.get(&key) {
|
||||
return Ok(pl);
|
||||
|
|
@ -473,6 +491,7 @@ impl VulkanRenderer {
|
|||
eotf: key.eotf.to_vulkan(),
|
||||
oetf: pipelines.oetf.to_vulkan(),
|
||||
descriptor_set_layouts: self.tex_descriptor_set_layouts.clone(),
|
||||
has_color_management_data,
|
||||
};
|
||||
let pl = self.device.create_pipeline2(info, push_size)?;
|
||||
pipelines.pipelines.set(key, pl.clone());
|
||||
|
|
@ -507,6 +526,7 @@ impl VulkanRenderer {
|
|||
eotf: key.eotf.to_vulkan(),
|
||||
oetf: fb_cd.transfer_function.to_vulkan(),
|
||||
descriptor_set_layouts,
|
||||
has_color_management_data: false,
|
||||
})?;
|
||||
pipelines.set(key, out.clone());
|
||||
Ok(out)
|
||||
|
|
@ -525,7 +545,6 @@ impl VulkanRenderer {
|
|||
return Ok(());
|
||||
};
|
||||
zone!("create_descriptor_buffers");
|
||||
let version = self.allocate_point();
|
||||
let memory = &mut *self.memory.borrow_mut();
|
||||
let sampler_writer = &mut memory.sampler_descriptor_buffer_writer;
|
||||
sampler_writer.clear();
|
||||
|
|
@ -538,30 +557,47 @@ impl VulkanRenderer {
|
|||
}
|
||||
let resource_writer = &mut memory.resource_descriptor_buffer_writer;
|
||||
resource_writer.clear();
|
||||
let uniform_buffer_descriptor_cache = memory
|
||||
.uniform_buffer_descriptor_cache
|
||||
.get_or_insert_with(|| {
|
||||
vec![0u8; self.device.uniform_buffer_descriptor_size].into_boxed_slice()
|
||||
});
|
||||
if let Some(bb) = bb {
|
||||
let layout = self.out_descriptor_set_layout.as_ref().unwrap();
|
||||
let offset = resource_writer.next_offset();
|
||||
bb.descriptor_buffer_offset.set(offset);
|
||||
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);
|
||||
}
|
||||
let tex_descriptor_set_layout = &self.tex_descriptor_set_layouts[1];
|
||||
for pass in RenderPass::variants() {
|
||||
for cmd in &memory.ops[pass] {
|
||||
for cmd in &mut memory.ops[pass] {
|
||||
let VulkanOp::Tex(c) = cmd else {
|
||||
continue;
|
||||
};
|
||||
let tex = &c.tex;
|
||||
if tex.descriptor_buffer_version.replace(version) == version {
|
||||
continue;
|
||||
}
|
||||
let offset = resource_writer.next_offset();
|
||||
tex.descriptor_buffer_offset.set(offset);
|
||||
c.resource_descriptor_buffer_offset = resource_writer.next_offset();
|
||||
let mut writer = resource_writer.add_set(tex_descriptor_set_layout);
|
||||
writer.write(
|
||||
tex_descriptor_set_layout.offsets[0],
|
||||
&tex.sampled_image_descriptor,
|
||||
);
|
||||
if let Some(addr) = c.color_management_data_address {
|
||||
let uniform_buffer = DescriptorAddressInfoEXT::default()
|
||||
.address(addr)
|
||||
.range(size_of::<TexColorManagementData>() 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(
|
||||
tex_descriptor_set_layout.offsets[1],
|
||||
uniform_buffer_descriptor_cache,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
let mut infos = ArrayVec::<_, 2>::new();
|
||||
|
|
@ -569,12 +605,7 @@ impl VulkanRenderer {
|
|||
(&sampler_writer, &self.sampler_descriptor_buffer_cache),
|
||||
(&resource_writer, &self.resource_descriptor_buffer_cache),
|
||||
] {
|
||||
let mut min_alignment = 1;
|
||||
if self.device.is_anv {
|
||||
// https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/33903
|
||||
min_alignment = 4096;
|
||||
}
|
||||
let buffer = cache.allocate(writer.len() as DeviceSize, min_alignment)?;
|
||||
let buffer = cache.allocate(writer.len() as DeviceSize)?;
|
||||
buffer.buffer.allocation.upload(|ptr, _| unsafe {
|
||||
ptr::copy_nonoverlapping(writer.as_ptr(), ptr, writer.len())
|
||||
})?;
|
||||
|
|
@ -607,6 +638,7 @@ impl VulkanRenderer {
|
|||
memory.tex_targets.clear();
|
||||
memory.fill_targets.clear();
|
||||
memory.data_buffer.clear();
|
||||
memory.uniform_buffer_writer.clear();
|
||||
memory.color_transforms.map.clear();
|
||||
let sync = |memory: &mut Memory| {
|
||||
for pass in RenderPass::variants() {
|
||||
|
|
@ -751,6 +783,16 @@ impl VulkanRenderer {
|
|||
true => TexSourceType::HasAlpha,
|
||||
false => TexSourceType::Opaque,
|
||||
};
|
||||
let target_cd = match pass {
|
||||
RenderPass::BlendBuffer => blend_cd,
|
||||
RenderPass::FrameBuffer => fb_cd,
|
||||
};
|
||||
let color_management_data_address = memory.color_transforms.get_offset(
|
||||
&ct.cd.linear,
|
||||
target_cd,
|
||||
self.device.uniform_buffer_offset_mask,
|
||||
&mut memory.uniform_buffer_writer,
|
||||
);
|
||||
ops.push(VulkanOp::Tex(VulkanTexOp {
|
||||
tex: tex.clone(),
|
||||
range: lo..hi,
|
||||
|
|
@ -763,6 +805,8 @@ impl VulkanRenderer {
|
|||
range_address: 0,
|
||||
instances: 0,
|
||||
tex_cd: ct.cd.clone(),
|
||||
color_management_data_address,
|
||||
resource_descriptor_buffer_offset: 0,
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
|
@ -792,7 +836,7 @@ impl VulkanRenderer {
|
|||
if buf.is_empty() {
|
||||
return Ok(());
|
||||
}
|
||||
let buffer = self.shader_buffer_cache.allocate(buf.len() as _, 8)?;
|
||||
let buffer = self.shader_buffer_cache.allocate(buf.len() as _)?;
|
||||
buffer.buffer.allocation.upload(|ptr, _| unsafe {
|
||||
ptr::copy_nonoverlapping(buf.as_ptr(), ptr, buf.len());
|
||||
})?;
|
||||
|
|
@ -813,6 +857,33 @@ impl VulkanRenderer {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn create_uniform_buffer(&self) -> Result<(), VulkanError> {
|
||||
if self.device.descriptor_buffer.is_none() {
|
||||
return Ok(());
|
||||
}
|
||||
zone!("create_uniform_buffer");
|
||||
let memory = &mut *self.memory.borrow_mut();
|
||||
let buf = &memory.uniform_buffer_writer;
|
||||
if buf.is_empty() {
|
||||
return Ok(());
|
||||
}
|
||||
let buffer = self.uniform_buffer_cache.allocate(buf.len() as _)?;
|
||||
buffer.buffer.allocation.upload(|ptr, _| unsafe {
|
||||
ptr::copy_nonoverlapping(buf.as_ptr(), ptr, buf.len());
|
||||
})?;
|
||||
for ops in memory.ops.values_mut() {
|
||||
for op in ops {
|
||||
if let VulkanOp::Tex(c) = op {
|
||||
if let Some(addr) = &mut c.color_management_data_address {
|
||||
*addr += buffer.buffer.address;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
memory.used_buffers.push(buffer);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn collect_memory(&self) {
|
||||
zone!("collect_memory");
|
||||
let memory = &mut *self.memory.borrow_mut();
|
||||
|
|
@ -1126,6 +1197,7 @@ impl VulkanRenderer {
|
|||
&c.tex_cd,
|
||||
c.copy_type,
|
||||
c.source_type,
|
||||
c.color_management_data_address.is_some(),
|
||||
)?;
|
||||
bind(&pipeline);
|
||||
let image_info = DescriptorImageInfo::default()
|
||||
|
|
@ -1143,7 +1215,7 @@ impl VulkanRenderer {
|
|||
pipeline.pipeline_layout,
|
||||
0,
|
||||
&[0, 1],
|
||||
&[0, tex.descriptor_buffer_offset.get()],
|
||||
&[0, c.resource_descriptor_buffer_offset],
|
||||
);
|
||||
dev.cmd_push_constants(
|
||||
buf,
|
||||
|
|
@ -1219,7 +1291,6 @@ impl VulkanRenderer {
|
|||
buf: CommandBuffer,
|
||||
fb: &VulkanImage,
|
||||
fb_cd: &ColorDescription,
|
||||
bb: &VulkanImage,
|
||||
bb_cd: &ColorDescription,
|
||||
) -> Result<(), VulkanError> {
|
||||
zone!("blend_buffer_copy");
|
||||
|
|
@ -1239,7 +1310,7 @@ impl VulkanRenderer {
|
|||
pipeline.pipeline_layout,
|
||||
0,
|
||||
&[1],
|
||||
&[bb.descriptor_buffer_offset.get()],
|
||||
&[memory.blend_buffer_descriptor_buffer_offset],
|
||||
);
|
||||
dev.cmd_push_constants(
|
||||
buf,
|
||||
|
|
@ -1808,6 +1879,7 @@ impl VulkanRenderer {
|
|||
let buf = self.gfx_command_buffers.allocate()?;
|
||||
self.convert_ops(opts, bb_cd, fb_cd);
|
||||
self.create_data_buffer()?;
|
||||
self.create_uniform_buffer()?;
|
||||
self.collect_memory();
|
||||
self.begin_command_buffer(buf.buffer)?;
|
||||
self.create_descriptor_buffers(buf.buffer, bb)?;
|
||||
|
|
@ -1827,8 +1899,8 @@ impl VulkanRenderer {
|
|||
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)?;
|
||||
if bb.is_some() {
|
||||
self.blend_buffer_copy(buf.buffer, fb, fb_cd, bb_cd)?;
|
||||
}
|
||||
self.end_rendering(buf.buffer);
|
||||
}
|
||||
|
|
@ -2055,6 +2127,7 @@ struct ColorTransforms {
|
|||
|
||||
struct ColorTransform {
|
||||
matrix: ColorMatrix,
|
||||
offset: Option<DeviceSize>,
|
||||
}
|
||||
|
||||
impl ColorTransforms {
|
||||
|
|
@ -2070,7 +2143,10 @@ impl ColorTransforms {
|
|||
Entry::Occupied(o) => o.into_mut(),
|
||||
Entry::Vacant(e) => {
|
||||
let matrix = src.color_transform(&dst.linear);
|
||||
let ct = ColorTransform { matrix };
|
||||
let ct = ColorTransform {
|
||||
matrix,
|
||||
offset: None,
|
||||
};
|
||||
e.insert(ct)
|
||||
}
|
||||
};
|
||||
|
|
@ -2088,4 +2164,22 @@ impl ColorTransforms {
|
|||
};
|
||||
color
|
||||
}
|
||||
|
||||
fn get_offset(
|
||||
&mut self,
|
||||
src: &LinearColorDescription,
|
||||
dst: &ColorDescription,
|
||||
uniform_buffer_offset_mask: DeviceSize,
|
||||
writer: &mut GenericBufferWriter,
|
||||
) -> Option<DeviceSize> {
|
||||
let ct = self.get_or_create(src, dst)?;
|
||||
if ct.offset.is_none() {
|
||||
let data = TexColorManagementData {
|
||||
matrix: ct.matrix.to_f32(),
|
||||
};
|
||||
let offset = writer.write(uniform_buffer_offset_mask, &data);
|
||||
ct.offset = Some(offset);
|
||||
}
|
||||
ct.offset
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -61,6 +61,14 @@ pub struct TexPushConstants {
|
|||
|
||||
unsafe impl Packed for TexPushConstants {}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
#[repr(C, align(16))]
|
||||
pub struct TexColorManagementData {
|
||||
pub matrix: [[f32; 4]; 4],
|
||||
}
|
||||
|
||||
unsafe impl Packed for TexColorManagementData {}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
#[repr(C)]
|
||||
pub struct LegacyTexPushConstants {
|
||||
|
|
|
|||
|
|
@ -5,5 +5,6 @@ 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 uint eotf = 0;
|
||||
layout(constant_id = 3) const uint oetf = 0;
|
||||
layout(constant_id = 4) const bool has_matrix = false;
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,25 +1,35 @@
|
|||
#version 450
|
||||
|
||||
#extension GL_EXT_scalar_block_layout : require
|
||||
|
||||
#include "frag_spec_const.glsl"
|
||||
#include "transfer_functions.glsl"
|
||||
#include "tex.common.glsl"
|
||||
|
||||
layout(set = 0, binding = 0) uniform sampler sam;
|
||||
layout(set = 1, binding = 0) uniform texture2D tex;
|
||||
layout(set = 1, binding = 1, row_major, std430) uniform ColorManagementData {
|
||||
mat4x4 matrix;
|
||||
} cm_data;
|
||||
layout(location = 0) in vec2 tex_pos;
|
||||
layout(location = 0) out vec4 out_color;
|
||||
|
||||
void main() {
|
||||
vec4 c = textureLod(sampler2D(tex, sam), tex_pos, 0);
|
||||
if (eotf != oetf) {
|
||||
if (eotf != oetf || has_matrix) {
|
||||
vec3 rgb = c.rgb;
|
||||
if (src_has_alpha) {
|
||||
c.rgb /= mix(c.a, 1.0, c.a == 0.0);
|
||||
rgb /= mix(c.a, 1.0, c.a == 0.0);
|
||||
}
|
||||
c.rgb = apply_eotf(c.rgb);
|
||||
c.rgb = apply_oetf(c.rgb);
|
||||
rgb = apply_eotf(rgb);
|
||||
if (has_matrix) {
|
||||
rgb = (cm_data.matrix * vec4(rgb, 1.0)).rgb;
|
||||
}
|
||||
rgb = apply_oetf(rgb);
|
||||
if (src_has_alpha) {
|
||||
c.rgb *= c.a;
|
||||
rgb *= c.a;
|
||||
}
|
||||
c.rgb = rgb;
|
||||
}
|
||||
if (has_alpha_multiplier) {
|
||||
if (src_has_alpha) {
|
||||
|
|
|
|||
|
|
@ -460,8 +460,6 @@ impl VulkanRenderer {
|
|||
ty: VulkanImageMemory::Internal(shm),
|
||||
bridge: None,
|
||||
sampled_image_descriptor: self.sampled_image_descriptor(view),
|
||||
descriptor_buffer_version: Cell::new(0),
|
||||
descriptor_buffer_offset: Cell::new(0),
|
||||
execution_version: Cell::new(0),
|
||||
});
|
||||
let shm = match &img.ty {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue