[vk] remove usage of imageless framebuffers

Imageless framebuffers are not needed, we know which views will be attached to the render pass already. Even if we wanted to more aggressively cache imageless framebuffers that wouldn't be possible since they still require specifiying view usage, texture usage and view formats.

Removing usage of imageless framebuffers simplifies the code substantially.
This commit is contained in:
teoxoy 2025-04-23 15:10:52 +02:00 committed by Teodor Tanasoaia
parent 2bb8325f85
commit d4b46d6099
6 changed files with 22 additions and 199 deletions

View File

@ -44,9 +44,6 @@ pub struct PhysicalDeviceFeatures {
pub(super) descriptor_indexing: pub(super) descriptor_indexing:
Option<vk::PhysicalDeviceDescriptorIndexingFeaturesEXT<'static>>, Option<vk::PhysicalDeviceDescriptorIndexingFeaturesEXT<'static>>,
/// Features provided by `VK_KHR_imageless_framebuffer`, promoted to Vulkan 1.2.
imageless_framebuffer: Option<vk::PhysicalDeviceImagelessFramebufferFeaturesKHR<'static>>,
/// Features provided by `VK_KHR_timeline_semaphore`, promoted to Vulkan 1.2 /// Features provided by `VK_KHR_timeline_semaphore`, promoted to Vulkan 1.2
timeline_semaphore: Option<vk::PhysicalDeviceTimelineSemaphoreFeaturesKHR<'static>>, timeline_semaphore: Option<vk::PhysicalDeviceTimelineSemaphoreFeaturesKHR<'static>>,
@ -138,9 +135,6 @@ impl PhysicalDeviceFeatures {
if let Some(ref mut feature) = self.descriptor_indexing { if let Some(ref mut feature) = self.descriptor_indexing {
info = info.push_next(feature); info = info.push_next(feature);
} }
if let Some(ref mut feature) = self.imageless_framebuffer {
info = info.push_next(feature);
}
if let Some(ref mut feature) = self.timeline_semaphore { if let Some(ref mut feature) = self.timeline_semaphore {
info = info.push_next(feature); info = info.push_next(feature);
} }
@ -329,16 +323,6 @@ impl PhysicalDeviceFeatures {
} else { } else {
None None
}, },
imageless_framebuffer: if device_api_version >= vk::API_VERSION_1_2
|| enabled_extensions.contains(&khr::imageless_framebuffer::NAME)
{
Some(
vk::PhysicalDeviceImagelessFramebufferFeaturesKHR::default()
.imageless_framebuffer(private_caps.imageless_framebuffers),
)
} else {
None
},
timeline_semaphore: if device_api_version >= vk::API_VERSION_1_2 timeline_semaphore: if device_api_version >= vk::API_VERSION_1_2
|| enabled_extensions.contains(&khr::timeline_semaphore::NAME) || enabled_extensions.contains(&khr::timeline_semaphore::NAME)
{ {
@ -976,15 +960,6 @@ impl PhysicalDeviceProperties {
extensions.push(khr::image_format_list::NAME); extensions.push(khr::image_format_list::NAME);
} }
// Optional `VK_KHR_imageless_framebuffer`
if self.supports_extension(khr::imageless_framebuffer::NAME) {
extensions.push(khr::imageless_framebuffer::NAME);
// Require `VK_KHR_maintenance2` due to it being a dependency
if self.device_api_version < vk::API_VERSION_1_1 {
extensions.push(khr::maintenance2::NAME);
}
}
// Optional `VK_KHR_driver_properties` // Optional `VK_KHR_driver_properties`
if self.supports_extension(khr::driver_properties::NAME) { if self.supports_extension(khr::driver_properties::NAME) {
extensions.push(khr::driver_properties::NAME); extensions.push(khr::driver_properties::NAME);
@ -1420,15 +1395,6 @@ impl super::InstanceShared {
features2 = features2.push_next(next); features2 = features2.push_next(next);
} }
// `VK_KHR_imageless_framebuffer` is promoted to 1.2, but has no
// changes, so we can keep using the extension unconditionally.
if capabilities.supports_extension(khr::imageless_framebuffer::NAME) {
let next = features
.imageless_framebuffer
.insert(vk::PhysicalDeviceImagelessFramebufferFeaturesKHR::default());
features2 = features2.push_next(next);
}
// `VK_KHR_timeline_semaphore` is promoted to 1.2, but has no // `VK_KHR_timeline_semaphore` is promoted to 1.2, but has no
// changes, so we can keep using the extension unconditionally. // changes, so we can keep using the extension unconditionally.
if capabilities.supports_extension(khr::timeline_semaphore::NAME) { if capabilities.supports_extension(khr::timeline_semaphore::NAME) {
@ -1655,12 +1621,6 @@ impl super::Instance {
} }
let private_caps = super::PrivateCapabilities { let private_caps = super::PrivateCapabilities {
imageless_framebuffers: match phd_features.imageless_framebuffer {
Some(features) => features.imageless_framebuffer == vk::TRUE,
None => phd_features
.imageless_framebuffer
.is_some_and(|ext| ext.imageless_framebuffer != 0),
},
image_view_usage: phd_capabilities.device_api_version >= vk::API_VERSION_1_1 image_view_usage: phd_capabilities.device_api_version >= vk::API_VERSION_1_1
|| phd_capabilities.supports_extension(khr::maintenance2::NAME), || phd_capabilities.supports_extension(khr::maintenance2::NAME),
timeline_semaphores: match phd_features.timeline_semaphore { timeline_semaphores: match phd_features.timeline_semaphore {

View File

@ -714,7 +714,6 @@ impl crate::CommandEncoder for super::CommandEncoder {
) -> Result<(), crate::DeviceError> { ) -> Result<(), crate::DeviceError> {
let mut vk_clear_values = let mut vk_clear_values =
ArrayVec::<vk::ClearValue, { super::MAX_TOTAL_ATTACHMENTS }>::new(); ArrayVec::<vk::ClearValue, { super::MAX_TOTAL_ATTACHMENTS }>::new();
let mut vk_image_views = ArrayVec::<vk::ImageView, { super::MAX_TOTAL_ATTACHMENTS }>::new();
let mut rp_key = super::RenderPassKey::default(); let mut rp_key = super::RenderPassKey::default();
let mut fb_key = super::FramebufferKey { let mut fb_key = super::FramebufferKey {
attachments: ArrayVec::default(), attachments: ArrayVec::default(),
@ -728,7 +727,6 @@ impl crate::CommandEncoder for super::CommandEncoder {
vk_clear_values.push(vk::ClearValue { vk_clear_values.push(vk::ClearValue {
color: unsafe { cat.make_vk_clear_color() }, color: unsafe { cat.make_vk_clear_color() },
}); });
vk_image_views.push(cat.target.view.raw);
let color = super::ColorAttachmentKey { let color = super::ColorAttachmentKey {
base: cat.target.make_attachment_key(cat.ops, caps), base: cat.target.make_attachment_key(cat.ops, caps),
resolve: cat.resolve_target.as_ref().map(|target| { resolve: cat.resolve_target.as_ref().map(|target| {
@ -737,11 +735,10 @@ impl crate::CommandEncoder for super::CommandEncoder {
}; };
rp_key.colors.push(Some(color)); rp_key.colors.push(Some(color));
fb_key.attachments.push(cat.target.view.attachment.clone()); fb_key.attachments.push(cat.target.view.raw);
if let Some(ref at) = cat.resolve_target { if let Some(ref at) = cat.resolve_target {
vk_clear_values.push(unsafe { mem::zeroed() }); vk_clear_values.push(unsafe { mem::zeroed() });
vk_image_views.push(at.view.raw); fb_key.attachments.push(at.view.raw);
fb_key.attachments.push(at.view.attachment.clone());
} }
// Assert this attachment is valid for the detected multiview, as a sanity check // Assert this attachment is valid for the detected multiview, as a sanity check
@ -763,12 +760,11 @@ impl crate::CommandEncoder for super::CommandEncoder {
stencil: ds.clear_value.1, stencil: ds.clear_value.1,
}, },
}); });
vk_image_views.push(ds.target.view.raw);
rp_key.depth_stencil = Some(super::DepthStencilAttachmentKey { rp_key.depth_stencil = Some(super::DepthStencilAttachmentKey {
base: ds.target.make_attachment_key(ds.depth_ops, caps), base: ds.target.make_attachment_key(ds.depth_ops, caps),
stencil_ops: ds.stencil_ops, stencil_ops: ds.stencil_ops,
}); });
fb_key.attachments.push(ds.target.view.attachment.clone()); fb_key.attachments.push(ds.target.view.raw);
// Assert this attachment is valid for the detected multiview, as a sanity check // Assert this attachment is valid for the detected multiview, as a sanity check
// The driver crash for this is really bad on AMD, so the check is worth it // The driver crash for this is really bad on AMD, so the check is worth it
@ -801,19 +797,11 @@ impl crate::CommandEncoder for super::CommandEncoder {
.make_framebuffer(fb_key, raw_pass, desc.label) .make_framebuffer(fb_key, raw_pass, desc.label)
.unwrap(); .unwrap();
let mut vk_info = vk::RenderPassBeginInfo::default() let vk_info = vk::RenderPassBeginInfo::default()
.render_pass(raw_pass) .render_pass(raw_pass)
.render_area(render_area) .render_area(render_area)
.clear_values(&vk_clear_values) .clear_values(&vk_clear_values)
.framebuffer(raw_framebuffer); .framebuffer(raw_framebuffer);
let mut vk_attachment_info = if caps.imageless_framebuffers {
Some(vk::RenderPassAttachmentBeginInfo::default().attachments(&vk_image_views))
} else {
None
};
if let Some(attachment_info) = vk_attachment_info.as_mut() {
vk_info = vk_info.push_next(attachment_info);
}
if let Some(label) = desc.label { if let Some(label) = desc.label {
unsafe { self.begin_debug_marker(label) }; unsafe { self.begin_debug_marker(label) };

View File

@ -188,8 +188,8 @@ impl crate::Attachment<'_, super::TextureView> {
caps: &super::PrivateCapabilities, caps: &super::PrivateCapabilities,
) -> super::AttachmentKey { ) -> super::AttachmentKey {
super::AttachmentKey { super::AttachmentKey {
format: caps.map_texture_format(self.view.attachment.view_format), format: caps.map_texture_format(self.view.view_format),
layout: derive_image_layout(self.usage, self.view.attachment.view_format), layout: derive_image_layout(self.usage, self.view.view_format),
ops, ops,
} }
} }
@ -201,7 +201,6 @@ impl crate::ColorAttachment<'_, super::TextureView> {
match self match self
.target .target
.view .view
.attachment
.view_format .view_format
.sample_type(None, None) .sample_type(None, None)
.unwrap() .unwrap()

View File

@ -211,72 +211,18 @@ impl super::DeviceShared {
Ok(match self.framebuffers.lock().entry(key) { Ok(match self.framebuffers.lock().entry(key) {
Entry::Occupied(e) => *e.get(), Entry::Occupied(e) => *e.get(),
Entry::Vacant(e) => { Entry::Vacant(e) => {
let vk_views = e let vk_info = vk::FramebufferCreateInfo::default()
.key()
.attachments
.iter()
.map(|at| at.raw)
.collect::<ArrayVec<_, { super::MAX_TOTAL_ATTACHMENTS }>>();
let vk_view_formats = e
.key()
.attachments
.iter()
.map(|at| self.private_caps.map_texture_format(at.view_format))
.collect::<ArrayVec<_, { super::MAX_TOTAL_ATTACHMENTS }>>();
let vk_view_formats_list = e
.key()
.attachments
.iter()
.map(|at| at.raw_view_formats.clone())
.collect::<ArrayVec<_, { super::MAX_TOTAL_ATTACHMENTS }>>();
let vk_image_infos = e
.key()
.attachments
.iter()
.enumerate()
.map(|(i, at)| {
let mut info = vk::FramebufferAttachmentImageInfo::default()
.usage(conv::map_texture_usage(at.view_usage))
.flags(at.raw_image_flags)
.width(e.key().extent.width)
.height(e.key().extent.height)
.layer_count(e.key().extent.depth_or_array_layers);
// https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VkRenderPassBeginInfo.html#VUID-VkRenderPassBeginInfo-framebuffer-03214
if vk_view_formats_list[i].is_empty() {
info = info.view_formats(&vk_view_formats[i..i + 1]);
} else {
info = info.view_formats(&vk_view_formats_list[i]);
};
info
})
.collect::<ArrayVec<_, { super::MAX_TOTAL_ATTACHMENTS }>>();
let mut vk_attachment_info = vk::FramebufferAttachmentsCreateInfo::default()
.attachment_image_infos(&vk_image_infos);
let mut vk_info = vk::FramebufferCreateInfo::default()
.render_pass(raw_pass) .render_pass(raw_pass)
.width(e.key().extent.width) .width(e.key().extent.width)
.height(e.key().extent.height) .height(e.key().extent.height)
.layers(e.key().extent.depth_or_array_layers); .layers(e.key().extent.depth_or_array_layers)
.attachments(&e.key().attachments);
if self.private_caps.imageless_framebuffers { let raw = unsafe { self.raw.create_framebuffer(&vk_info, None).unwrap() };
//TODO: https://github.com/MaikKlein/ash/issues/450
vk_info = vk_info
.flags(vk::FramebufferCreateFlags::IMAGELESS_KHR)
.push_next(&mut vk_attachment_info);
vk_info.attachment_count = e.key().attachments.len() as u32;
} else {
vk_info = vk_info.attachments(&vk_views);
}
*e.insert(unsafe {
let raw = self.raw.create_framebuffer(&vk_info, None).unwrap();
if let Some(label) = pass_label { if let Some(label) = pass_label {
self.set_object_name(raw, label); unsafe { self.set_object_name(raw, label) };
} }
raw *e.insert(raw)
})
} }
}) })
} }
@ -558,7 +504,6 @@ impl super::Device {
let original_format = self.shared.private_caps.map_texture_format(config.format); let original_format = self.shared.private_caps.map_texture_format(config.format);
let mut raw_flags = vk::SwapchainCreateFlagsKHR::empty(); let mut raw_flags = vk::SwapchainCreateFlagsKHR::empty();
let mut raw_view_formats: Vec<vk::Format> = vec![]; let mut raw_view_formats: Vec<vk::Format> = vec![];
let mut wgt_view_formats = vec![];
if !config.view_formats.is_empty() { if !config.view_formats.is_empty() {
raw_flags |= vk::SwapchainCreateFlagsKHR::MUTABLE_FORMAT; raw_flags |= vk::SwapchainCreateFlagsKHR::MUTABLE_FORMAT;
raw_view_formats = config raw_view_formats = config
@ -567,9 +512,6 @@ impl super::Device {
.map(|f| self.shared.private_caps.map_texture_format(*f)) .map(|f| self.shared.private_caps.map_texture_format(*f))
.collect(); .collect();
raw_view_formats.push(original_format); raw_view_formats.push(original_format);
wgt_view_formats.clone_from(&config.view_formats);
wgt_view_formats.push(config.format);
} }
let mut info = vk::SwapchainCreateInfoKHR::default() let mut info = vk::SwapchainCreateInfoKHR::default()
@ -639,12 +581,10 @@ impl super::Device {
Ok(super::Swapchain { Ok(super::Swapchain {
raw, raw,
raw_flags,
functor, functor,
device: Arc::clone(&self.shared), device: Arc::clone(&self.shared),
images, images,
config: config.clone(), config: config.clone(),
view_formats: wgt_view_formats,
surface_semaphores, surface_semaphores,
next_semaphore_index: 0, next_semaphore_index: 0,
next_present_time: None, next_present_time: None,
@ -686,11 +626,8 @@ impl super::Device {
drop_guard, drop_guard,
external_memory: None, external_memory: None,
block: None, block: None,
usage: desc.usage,
format: desc.format, format: desc.format,
raw_flags: vk::ImageCreateFlags::empty(),
copy_size: desc.copy_extent(), copy_size: desc.copy_extent(),
view_formats,
} }
} }
@ -734,11 +671,8 @@ impl super::Device {
let original_format = self.shared.private_caps.map_texture_format(desc.format); let original_format = self.shared.private_caps.map_texture_format(desc.format);
let mut vk_view_formats = vec![]; let mut vk_view_formats = vec![];
let mut wgt_view_formats = vec![];
if !desc.view_formats.is_empty() { if !desc.view_formats.is_empty() {
raw_flags |= vk::ImageCreateFlags::MUTABLE_FORMAT; raw_flags |= vk::ImageCreateFlags::MUTABLE_FORMAT;
wgt_view_formats.clone_from(&desc.view_formats);
wgt_view_formats.push(desc.format);
if self.shared.private_caps.image_format_list { if self.shared.private_caps.image_format_list {
vk_view_formats = desc vk_view_formats = desc
@ -788,8 +722,6 @@ impl super::Device {
raw, raw,
requirements: req, requirements: req,
copy_size, copy_size,
view_formats: wgt_view_formats,
raw_flags,
}) })
} }
@ -851,11 +783,8 @@ impl super::Device {
drop_guard: None, drop_guard: None,
external_memory: Some(memory), external_memory: Some(memory),
block: None, block: None,
usage: desc.usage,
format: desc.format, format: desc.format,
raw_flags: image.raw_flags,
copy_size: image.copy_size, copy_size: image.copy_size,
view_formats: image.view_formats,
}) })
} }
@ -1326,11 +1255,8 @@ impl crate::Device for super::Device {
drop_guard: None, drop_guard: None,
external_memory: None, external_memory: None,
block: Some(block), block: Some(block),
usage: desc.usage,
format: desc.format, format: desc.format,
raw_flags: image.raw_flags,
copy_size: image.copy_size, copy_size: image.copy_size,
view_formats: image.view_formats,
}) })
} }
unsafe fn destroy_texture(&self, texture: super::Texture) { unsafe fn destroy_texture(&self, texture: super::Texture) {
@ -1369,14 +1295,11 @@ impl crate::Device for super::Device {
NonZeroU32::new(subresource_range.layer_count).expect("Unexpected zero layer count"); NonZeroU32::new(subresource_range.layer_count).expect("Unexpected zero layer count");
let mut image_view_info; let mut image_view_info;
let view_usage = if self.shared.private_caps.image_view_usage && !desc.usage.is_empty() { if self.shared.private_caps.image_view_usage && !desc.usage.is_empty() {
image_view_info = image_view_info =
vk::ImageViewUsageCreateInfo::default().usage(conv::map_texture_usage(desc.usage)); vk::ImageViewUsageCreateInfo::default().usage(conv::map_texture_usage(desc.usage));
vk_info = vk_info.push_next(&mut image_view_info); vk_info = vk_info.push_next(&mut image_view_info);
desc.usage }
} else {
texture.usage
};
let raw = unsafe { self.shared.raw.create_image_view(&vk_info, None) } let raw = unsafe { self.shared.raw.create_image_view(&vk_info, None) }
.map_err(super::map_host_device_oom_and_ioca_err)?; .map_err(super::map_host_device_oom_and_ioca_err)?;
@ -1385,39 +1308,23 @@ impl crate::Device for super::Device {
unsafe { self.shared.set_object_name(raw, label) }; unsafe { self.shared.set_object_name(raw, label) };
} }
let attachment = super::FramebufferAttachment {
raw: if self.shared.private_caps.imageless_framebuffers {
vk::ImageView::null()
} else {
raw
},
raw_image_flags: texture.raw_flags,
view_usage,
view_format: desc.format,
raw_view_formats: texture
.view_formats
.iter()
.map(|tf| self.shared.private_caps.map_texture_format(*tf))
.collect(),
};
self.counters.texture_views.add(1); self.counters.texture_views.add(1);
Ok(super::TextureView { Ok(super::TextureView {
raw, raw,
layers, layers,
attachment, view_format: desc.format,
}) })
} }
unsafe fn destroy_texture_view(&self, view: super::TextureView) { unsafe fn destroy_texture_view(&self, view: super::TextureView) {
if !self.shared.private_caps.imageless_framebuffers { {
let mut fbuf_lock = self.shared.framebuffers.lock(); let mut fbuf_lock = self.shared.framebuffers.lock();
for (key, &raw_fbuf) in fbuf_lock.iter() { for (key, &raw_fbuf) in fbuf_lock.iter() {
if key.attachments.iter().any(|at| at.raw == view.raw) { if key.attachments.iter().any(|at_view| *at_view == view.raw) {
unsafe { self.shared.raw.destroy_framebuffer(raw_fbuf, None) }; unsafe { self.shared.raw.destroy_framebuffer(raw_fbuf, None) };
} }
} }
fbuf_lock.retain(|key, _| !key.attachments.iter().any(|at| at.raw == view.raw)); fbuf_lock.retain(|key, _| !key.attachments.iter().any(|at_view| *at_view == view.raw));
} }
unsafe { self.shared.raw.destroy_image_view(view.raw, None) }; unsafe { self.shared.raw.destroy_image_view(view.raw, None) };
@ -1855,7 +1762,7 @@ impl crate::Device for super::Device {
|binding| { |binding| {
let layout = conv::derive_image_layout( let layout = conv::derive_image_layout(
binding.usage, binding.usage,
binding.view.attachment.view_format, binding.view.view_format,
); );
vk::DescriptorImageInfo::default() vk::DescriptorImageInfo::default()
.image_view(binding.view.raw) .image_view(binding.view.raw)
@ -3177,6 +3084,4 @@ struct ImageWithoutMemory {
raw: vk::Image, raw: vk::Image,
requirements: vk::MemoryRequirements, requirements: vk::MemoryRequirements,
copy_size: crate::CopyExtent, copy_size: crate::CopyExtent,
view_formats: Vec<wgt::TextureFormat>,
raw_flags: vk::ImageCreateFlags,
} }

View File

@ -1108,16 +1108,6 @@ impl crate::Surface for super::Surface {
return Err(crate::SurfaceError::Outdated); return Err(crate::SurfaceError::Outdated);
} }
// https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VkRenderPassBeginInfo.html#VUID-VkRenderPassBeginInfo-framebuffer-03209
let raw_flags = if swapchain
.raw_flags
.contains(vk::SwapchainCreateFlagsKHR::MUTABLE_FORMAT)
{
vk::ImageCreateFlags::MUTABLE_FORMAT | vk::ImageCreateFlags::EXTENDED_USAGE
} else {
vk::ImageCreateFlags::empty()
};
let texture = super::SurfaceTexture { let texture = super::SurfaceTexture {
index, index,
texture: super::Texture { texture: super::Texture {
@ -1125,15 +1115,12 @@ impl crate::Surface for super::Surface {
drop_guard: None, drop_guard: None,
block: None, block: None,
external_memory: None, external_memory: None,
usage: swapchain.config.usage,
format: swapchain.config.format, format: swapchain.config.format,
raw_flags,
copy_size: crate::CopyExtent { copy_size: crate::CopyExtent {
width: swapchain.config.extent.width, width: swapchain.config.extent.width,
height: swapchain.config.extent.height, height: swapchain.config.extent.height,
depth: 1, depth: 1,
}, },
view_formats: swapchain.view_formats.clone(),
}, },
surface_semaphores: swapchain_semaphores_arc, surface_semaphores: swapchain_semaphores_arc,
}; };

View File

@ -340,12 +340,10 @@ impl SwapchainImageSemaphores {
struct Swapchain { struct Swapchain {
raw: vk::SwapchainKHR, raw: vk::SwapchainKHR,
raw_flags: vk::SwapchainCreateFlagsKHR,
functor: khr::swapchain::Device, functor: khr::swapchain::Device,
device: Arc<DeviceShared>, device: Arc<DeviceShared>,
images: Vec<vk::Image>, images: Vec<vk::Image>,
config: crate::SurfaceConfiguration, config: crate::SurfaceConfiguration,
view_formats: Vec<wgt::TextureFormat>,
/// One wait semaphore per swapchain image. This will be associated with the /// One wait semaphore per swapchain image. This will be associated with the
/// surface texture, and later collected during submission. /// surface texture, and later collected during submission.
/// ///
@ -488,7 +486,6 @@ struct RayTracingDeviceExtensionFunctions {
/// device geometry, but affect the code paths taken internally. /// device geometry, but affect the code paths taken internally.
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
struct PrivateCapabilities { struct PrivateCapabilities {
imageless_framebuffers: bool,
image_view_usage: bool, image_view_usage: bool,
timeline_semaphores: bool, timeline_semaphores: bool,
texture_d24: bool, texture_d24: bool,
@ -605,19 +602,9 @@ struct RenderPassKey {
multiview: Option<NonZeroU32>, multiview: Option<NonZeroU32>,
} }
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
struct FramebufferAttachment {
/// Can be NULL if the framebuffer is image-less
raw: vk::ImageView,
raw_image_flags: vk::ImageCreateFlags,
view_usage: wgt::TextureUses,
view_format: wgt::TextureFormat,
raw_view_formats: Vec<vk::Format>,
}
#[derive(Clone, Eq, Hash, PartialEq)] #[derive(Clone, Eq, Hash, PartialEq)]
struct FramebufferKey { struct FramebufferKey {
attachments: ArrayVec<FramebufferAttachment, { MAX_TOTAL_ATTACHMENTS }>, attachments: ArrayVec<vk::ImageView, { MAX_TOTAL_ATTACHMENTS }>,
extent: wgt::Extent3d, extent: wgt::Extent3d,
sample_count: u32, sample_count: u32,
} }
@ -797,11 +784,8 @@ pub struct Texture {
drop_guard: Option<crate::DropGuard>, drop_guard: Option<crate::DropGuard>,
external_memory: Option<vk::DeviceMemory>, external_memory: Option<vk::DeviceMemory>,
block: Option<gpu_alloc::MemoryBlock<vk::DeviceMemory>>, block: Option<gpu_alloc::MemoryBlock<vk::DeviceMemory>>,
usage: wgt::TextureUses,
format: wgt::TextureFormat, format: wgt::TextureFormat,
raw_flags: vk::ImageCreateFlags,
copy_size: crate::CopyExtent, copy_size: crate::CopyExtent,
view_formats: Vec<wgt::TextureFormat>,
} }
impl crate::DynTexture for Texture {} impl crate::DynTexture for Texture {}
@ -819,7 +803,7 @@ impl Texture {
pub struct TextureView { pub struct TextureView {
raw: vk::ImageView, raw: vk::ImageView,
layers: NonZeroU32, layers: NonZeroU32,
attachment: FramebufferAttachment, view_format: wgt::TextureFormat,
} }
impl crate::DynTextureView for TextureView {} impl crate::DynTextureView for TextureView {}