Skip to content

Commit 7df7c6c

Browse files
committed
vulkan: texture_from_d3d11_shared_handle
1 parent c2e0ad2 commit 7df7c6c

File tree

2 files changed

+127
-0
lines changed

2 files changed

+127
-0
lines changed

wgpu-hal/src/vulkan/device.rs

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -686,6 +686,7 @@ impl super::Device {
686686
super::Texture {
687687
raw: vk_image,
688688
drop_guard,
689+
external_memory: None,
689690
block: None,
690691
usage: desc.usage,
691692
format: desc.format,
@@ -695,6 +696,127 @@ impl super::Device {
695696
}
696697
}
697698

699+
#[cfg(windows)]
700+
unsafe fn find_memory_type_index(
701+
&self,
702+
type_bits: u32,
703+
flags: vk::MemoryPropertyFlags,
704+
) -> Option<usize> {
705+
let mem_properties = self
706+
.shared
707+
.instance
708+
.raw
709+
.get_physical_device_memory_properties(self.shared.physical_device);
710+
711+
for (i, mem_ty) in mem_properties
712+
.memory_types_as_slice()
713+
.into_iter()
714+
.enumerate()
715+
{
716+
if type_bits & (1 << i) != 0 && mem_ty.property_flags & flags == flags {
717+
return Some(i);
718+
}
719+
}
720+
721+
None
722+
}
723+
724+
/// # Safety
725+
///
726+
#[cfg(windows)]
727+
pub unsafe fn texture_from_d3d11_shared_handle(
728+
&self,
729+
d3d11_shared_handle: vk::HANDLE,
730+
desc: &crate::TextureDescriptor,
731+
) -> ash::prelude::VkResult<super::Texture> {
732+
let copy_size = desc.copy_extent();
733+
734+
let mut raw_flags = vk::ImageCreateFlags::empty();
735+
if desc.is_cube_compatible() {
736+
raw_flags |= vk::ImageCreateFlags::CUBE_COMPATIBLE;
737+
}
738+
739+
let original_format = self.shared.private_caps.map_texture_format(desc.format);
740+
let mut vk_view_formats = vec![];
741+
let mut wgt_view_formats = vec![];
742+
if !desc.view_formats.is_empty() {
743+
raw_flags |= vk::ImageCreateFlags::MUTABLE_FORMAT;
744+
wgt_view_formats.clone_from(&desc.view_formats);
745+
wgt_view_formats.push(desc.format);
746+
747+
if self.shared.private_caps.image_format_list {
748+
vk_view_formats = desc
749+
.view_formats
750+
.iter()
751+
.map(|f| self.shared.private_caps.map_texture_format(*f))
752+
.collect();
753+
vk_view_formats.push(original_format)
754+
}
755+
}
756+
if desc.format.is_multi_planar_format() {
757+
raw_flags |= vk::ImageCreateFlags::MUTABLE_FORMAT;
758+
}
759+
760+
let mut vk_info = vk::ImageCreateInfo::default()
761+
.flags(raw_flags)
762+
.image_type(conv::map_texture_dimension(desc.dimension))
763+
.format(original_format)
764+
.extent(conv::map_copy_extent(&copy_size))
765+
.mip_levels(desc.mip_level_count)
766+
.array_layers(desc.array_layer_count())
767+
.samples(vk::SampleCountFlags::from_raw(desc.sample_count))
768+
.tiling(vk::ImageTiling::OPTIMAL)
769+
.usage(conv::map_texture_usage(desc.usage))
770+
.sharing_mode(vk::SharingMode::EXCLUSIVE)
771+
.initial_layout(vk::ImageLayout::UNDEFINED);
772+
773+
let mut format_list_info = vk::ImageFormatListCreateInfo::default();
774+
if !vk_view_formats.is_empty() {
775+
format_list_info = format_list_info.view_formats(&vk_view_formats);
776+
vk_info = vk_info.push_next(&mut format_list_info);
777+
}
778+
779+
let mut external_memory_image_info = vk::ExternalMemoryImageCreateInfo::default()
780+
.handle_types(vk::ExternalMemoryHandleTypeFlags::D3D11_TEXTURE_KMT);
781+
vk_info = vk_info.push_next(&mut external_memory_image_info);
782+
783+
let raw = unsafe { self.shared.raw.create_image(&vk_info, None)? };
784+
let req = unsafe { self.shared.raw.get_image_memory_requirements(raw) };
785+
786+
let mut import_memory_info = vk::ImportMemoryWin32HandleInfoKHR::default()
787+
.handle_type(vk::ExternalMemoryHandleTypeFlags::D3D11_TEXTURE_KMT)
788+
.handle(d3d11_shared_handle);
789+
790+
let Some(mem_type_index) = self
791+
.find_memory_type_index(req.memory_type_bits, vk::MemoryPropertyFlags::DEVICE_LOCAL)
792+
else {
793+
return Err(vk::Result::ERROR_UNKNOWN);
794+
};
795+
796+
let memory_allocate_info = vk::MemoryAllocateInfo::default()
797+
.allocation_size(req.size)
798+
.memory_type_index(mem_type_index as _)
799+
.push_next(&mut import_memory_info);
800+
let memory = unsafe {
801+
self.shared
802+
.raw
803+
.allocate_memory(&memory_allocate_info, None)?
804+
};
805+
unsafe { self.shared.raw.bind_image_memory(raw, memory, 0)? };
806+
807+
Ok(super::Texture {
808+
raw,
809+
drop_guard: None,
810+
external_memory: Some(memory),
811+
block: None,
812+
usage: desc.usage,
813+
format: desc.format,
814+
raw_flags,
815+
copy_size,
816+
view_formats: wgt_view_formats,
817+
})
818+
}
819+
698820
/// # Safety
699821
///
700822
/// - `vk_buffer`'s memory must be managed by the caller
@@ -1117,6 +1239,7 @@ impl crate::Device for super::Device {
11171239
Ok(super::Texture {
11181240
raw,
11191241
drop_guard: None,
1242+
external_memory: None,
11201243
block: Some(block),
11211244
usage: desc.usage,
11221245
format: desc.format,
@@ -1129,6 +1252,9 @@ impl crate::Device for super::Device {
11291252
if texture.drop_guard.is_none() {
11301253
unsafe { self.shared.raw.destroy_image(texture.raw, None) };
11311254
}
1255+
if let Some(memory) = texture.external_memory {
1256+
self.shared.raw.free_memory(memory, None);
1257+
}
11321258
if let Some(block) = texture.block {
11331259
self.counters.texture_memory.sub(block.size() as isize);
11341260

wgpu-hal/src/vulkan/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -754,6 +754,7 @@ impl crate::DynAccelerationStructure for AccelerationStructure {}
754754
pub struct Texture {
755755
raw: vk::Image,
756756
drop_guard: Option<crate::DropGuard>,
757+
external_memory: Option<vk::DeviceMemory>,
757758
block: Option<gpu_alloc::MemoryBlock<vk::DeviceMemory>>,
758759
usage: crate::TextureUses,
759760
format: wgt::TextureFormat,

0 commit comments

Comments
 (0)