mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-27 06:43:32 +00:00
Bug 1921379 - Alloc DMA buffer in VKImage for WebGPU presentation on Linux r=webgpu-reviewers,nical
Allocate dmabuf in VKImage, since direct dmabuf creation by gbm_bo_* is not reliable and comes with various issue. Texture of swap chain uses vk::ImageCreateFlags::ALIAS(VK_IMAGE_CREATE_ALIAS_BIT). wgpu_server_adapter_request_device() allocates vulkan device for enabling the following extensions that is necessary for dmabuf support. - khr::external_memory_fd - ext::external_memory_dma_buf - ext::image_drm_format_modifier - khr::external_semaphore_fd Differential Revision: https://phabricator.services.mozilla.com/D223910
This commit is contained in:
parent
ff7475fdea
commit
b96d339c5b
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -7096,6 +7096,7 @@ name = "wgpu_bindings"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"arrayvec",
|
"arrayvec",
|
||||||
|
"ash",
|
||||||
"bincode",
|
"bincode",
|
||||||
"log",
|
"log",
|
||||||
"nsstring",
|
"nsstring",
|
||||||
|
@ -79,7 +79,7 @@ UniquePtr<ExternalTextureDMABuf> ExternalTextureDMABuf::Create(
|
|||||||
}
|
}
|
||||||
|
|
||||||
ExternalTextureDMABuf::ExternalTextureDMABuf(
|
ExternalTextureDMABuf::ExternalTextureDMABuf(
|
||||||
UniquePtr<ffi::WGPUVkImageHandle> aVkImageHandle, const uint32_t aWidth,
|
UniquePtr<ffi::WGPUVkImageHandle>&& aVkImageHandle, const uint32_t aWidth,
|
||||||
const uint32_t aHeight, const struct ffi::WGPUTextureFormat aFormat,
|
const uint32_t aHeight, const struct ffi::WGPUTextureFormat aFormat,
|
||||||
const ffi::WGPUTextureUsages aUsage, RefPtr<DMABufSurface>&& aSurface,
|
const ffi::WGPUTextureUsages aUsage, RefPtr<DMABufSurface>&& aSurface,
|
||||||
const layers::SurfaceDescriptorDMABuf& aSurfaceDescriptor)
|
const layers::SurfaceDescriptorDMABuf& aSurfaceDescriptor)
|
||||||
|
@ -24,7 +24,7 @@ class ExternalTextureDMABuf final : public ExternalTexture {
|
|||||||
const ffi::WGPUTextureUsages aUsage);
|
const ffi::WGPUTextureUsages aUsage);
|
||||||
|
|
||||||
ExternalTextureDMABuf(
|
ExternalTextureDMABuf(
|
||||||
UniquePtr<ffi::WGPUVkImageHandle> aVkImageHandle, const uint32_t aWidth,
|
UniquePtr<ffi::WGPUVkImageHandle>&& aVkImageHandle, const uint32_t aWidth,
|
||||||
const uint32_t aHeight, const struct ffi::WGPUTextureFormat aFormat,
|
const uint32_t aHeight, const struct ffi::WGPUTextureFormat aFormat,
|
||||||
const ffi::WGPUTextureUsages aUsage, RefPtr<DMABufSurface>&& aSurface,
|
const ffi::WGPUTextureUsages aUsage, RefPtr<DMABufSurface>&& aSurface,
|
||||||
const layers::SurfaceDescriptorDMABuf& aSurfaceDescriptor);
|
const layers::SurfaceDescriptorDMABuf& aSurfaceDescriptor);
|
||||||
|
@ -108,6 +108,7 @@ extern int32_t wgpu_server_get_dma_buf_fd(void* aParam, WGPUTextureId aId) {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if !defined(XP_MACOSX)
|
||||||
extern WGPUVkImageHandle* wgpu_server_get_vk_image_handle(void* aParam,
|
extern WGPUVkImageHandle* wgpu_server_get_vk_image_handle(void* aParam,
|
||||||
WGPUTextureId aId) {
|
WGPUTextureId aId) {
|
||||||
auto* parent = static_cast<WebGPUParent*>(aParam);
|
auto* parent = static_cast<WebGPUParent*>(aParam);
|
||||||
@ -118,16 +119,17 @@ extern WGPUVkImageHandle* wgpu_server_get_vk_image_handle(void* aParam,
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(MOZ_WIDGET_GTK)
|
# if defined(MOZ_WIDGET_GTK)
|
||||||
auto* textureDMABuf = texture->AsExternalTextureDMABuf();
|
auto* textureDMABuf = texture->AsExternalTextureDMABuf();
|
||||||
if (!textureDMABuf) {
|
if (!textureDMABuf) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
return textureDMABuf->GetHandle();
|
return textureDMABuf->GetHandle();
|
||||||
#else
|
# else
|
||||||
return nullptr;
|
return nullptr;
|
||||||
#endif
|
# endif
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
} // namespace ffi
|
} // namespace ffi
|
||||||
|
|
||||||
|
@ -3164,12 +3164,13 @@ void gfxPlatform::InitWebGPUConfig() {
|
|||||||
|
|
||||||
gfxVars::SetAllowWebGPU(feature.IsEnabled());
|
gfxVars::SetAllowWebGPU(feature.IsEnabled());
|
||||||
|
|
||||||
|
if (StaticPrefs::dom_webgpu_allow_present_without_readback()
|
||||||
#if XP_WIN
|
#if XP_WIN
|
||||||
if (IsWin10CreatorsUpdateOrLater() &&
|
&& IsWin10CreatorsUpdateOrLater()
|
||||||
StaticPrefs::dom_webgpu_allow_present_without_readback()) {
|
#endif
|
||||||
|
) {
|
||||||
gfxVars::SetAllowWebGPUPresentWithoutReadback(true);
|
gfxVars::SetAllowWebGPUPresentWithoutReadback(true);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef XP_WIN
|
#ifdef XP_WIN
|
||||||
|
@ -65,3 +65,4 @@ serde = "1"
|
|||||||
nsstring = { path = "../../xpcom/rust/nsstring" }
|
nsstring = { path = "../../xpcom/rust/nsstring" }
|
||||||
static_prefs = { path = "../../modules/libpref/init/static_prefs" }
|
static_prefs = { path = "../../modules/libpref/init/static_prefs" }
|
||||||
arrayvec = "0.7"
|
arrayvec = "0.7"
|
||||||
|
ash = "0.38"
|
||||||
|
@ -19,6 +19,8 @@ use wgh::Instance;
|
|||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
#[cfg(not(any(target_os = "windows", target_os = "macos", target_os = "ios")))]
|
||||||
|
use std::os::fd::{FromRawFd, IntoRawFd, OwnedFd, RawFd};
|
||||||
use std::os::raw::{c_char, c_void};
|
use std::os::raw::{c_char, c_void};
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
use std::slice;
|
use std::slice;
|
||||||
@ -31,6 +33,9 @@ use std::ffi::{c_long, c_ulong};
|
|||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
use windows::Win32::{Foundation, Graphics::Direct3D12};
|
use windows::Win32::{Foundation, Graphics::Direct3D12};
|
||||||
|
|
||||||
|
#[cfg(not(any(target_os = "macos", target_os = "ios")))]
|
||||||
|
use ash::{khr, vk};
|
||||||
|
|
||||||
// The seemingly redundant u64 suffixes help cbindgen with generating the right C++ code.
|
// The seemingly redundant u64 suffixes help cbindgen with generating the right C++ code.
|
||||||
// See https://github.com/mozilla/cbindgen/issues/849.
|
// See https://github.com/mozilla/cbindgen/issues/849.
|
||||||
|
|
||||||
@ -224,6 +229,35 @@ fn support_use_external_texture_in_swap_chain(
|
|||||||
return backend == wgt::Backend::Dx12 && is_hardware;
|
return backend == wgt::Backend::Dx12 && is_hardware;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
{
|
||||||
|
let support = if backend != wgt::Backend::Vulkan {
|
||||||
|
false
|
||||||
|
} else {
|
||||||
|
unsafe {
|
||||||
|
global.adapter_as_hal::<wgc::api::Vulkan, _, bool>(self_id, |hal_adapter| {
|
||||||
|
let hal_adapter = match hal_adapter {
|
||||||
|
None => {
|
||||||
|
let msg = CString::new(format!("Vulkan adapter is invalid")).unwrap();
|
||||||
|
gfx_critical_note(msg.as_ptr());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Some(hal_adapter) => hal_adapter,
|
||||||
|
};
|
||||||
|
|
||||||
|
let capabilities = hal_adapter.physical_device_capabilities();
|
||||||
|
|
||||||
|
capabilities.supports_extension(khr::external_memory_fd::NAME)
|
||||||
|
&& capabilities.supports_extension(ash::ext::external_memory_dma_buf::NAME)
|
||||||
|
&& capabilities
|
||||||
|
.supports_extension(ash::ext::image_drm_format_modifier::NAME)
|
||||||
|
&& capabilities.supports_extension(khr::external_semaphore_fd::NAME)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return support;
|
||||||
|
}
|
||||||
|
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -312,6 +346,148 @@ pub unsafe extern "C" fn wgpu_server_adapter_request_device(
|
|||||||
// TODO: in https://github.com/gfx-rs/wgpu/pull/3626/files#diff-033343814319f5a6bd781494692ea626f06f6c3acc0753a12c867b53a646c34eR97
|
// TODO: in https://github.com/gfx-rs/wgpu/pull/3626/files#diff-033343814319f5a6bd781494692ea626f06f6c3acc0753a12c867b53a646c34eR97
|
||||||
// which introduced the queue id parameter, the queue id is also the device id. I don't know how applicable this is to
|
// which introduced the queue id parameter, the queue id is also the device id. I don't know how applicable this is to
|
||||||
// other situations (this one in particular).
|
// other situations (this one in particular).
|
||||||
|
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
{
|
||||||
|
let support_dma_buf =
|
||||||
|
global.adapter_as_hal::<wgc::api::Vulkan, _, bool>(self_id, |hal_adapter| {
|
||||||
|
let hal_adapter = match hal_adapter {
|
||||||
|
None => {
|
||||||
|
let msg = CString::new(format!("Vulkan adapter is invalid")).unwrap();
|
||||||
|
gfx_critical_note(msg.as_ptr());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Some(hal_adapter) => hal_adapter,
|
||||||
|
};
|
||||||
|
|
||||||
|
let capabilities = hal_adapter.physical_device_capabilities();
|
||||||
|
|
||||||
|
capabilities.supports_extension(khr::external_memory_fd::NAME)
|
||||||
|
&& capabilities.supports_extension(ash::ext::external_memory_dma_buf::NAME)
|
||||||
|
&& capabilities.supports_extension(ash::ext::image_drm_format_modifier::NAME)
|
||||||
|
&& capabilities.supports_extension(khr::external_semaphore_fd::NAME)
|
||||||
|
});
|
||||||
|
|
||||||
|
if support_dma_buf {
|
||||||
|
let hal_device = global
|
||||||
|
.adapter_as_hal::<wgc::api::Vulkan, _, Option<wgh::OpenDevice<wgh::api::Vulkan>>>(
|
||||||
|
self_id,
|
||||||
|
|hal_adapter| {
|
||||||
|
let hal_adapter = match hal_adapter {
|
||||||
|
None => {
|
||||||
|
let msg =
|
||||||
|
CString::new(format!("Vulkan adapter is invalid")).unwrap();
|
||||||
|
gfx_critical_note(msg.as_ptr());
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
Some(hal_adapter) => hal_adapter,
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut enabled_extensions =
|
||||||
|
hal_adapter.required_device_extensions(desc.required_features);
|
||||||
|
enabled_extensions.push(khr::external_memory_fd::NAME);
|
||||||
|
enabled_extensions.push(ash::ext::external_memory_dma_buf::NAME);
|
||||||
|
enabled_extensions.push(ash::ext::image_drm_format_modifier::NAME);
|
||||||
|
enabled_extensions.push(khr::external_semaphore_fd::NAME);
|
||||||
|
|
||||||
|
let mut enabled_phd_features = hal_adapter
|
||||||
|
.physical_device_features(&enabled_extensions, desc.required_features);
|
||||||
|
|
||||||
|
let raw_instance = hal_adapter.shared_instance().raw_instance();
|
||||||
|
let raw_physical_device = hal_adapter.raw_physical_device();
|
||||||
|
|
||||||
|
let queue_family_index = raw_instance
|
||||||
|
.get_physical_device_queue_family_properties(raw_physical_device)
|
||||||
|
.into_iter()
|
||||||
|
.enumerate()
|
||||||
|
.find_map(|(queue_family_index, info)| {
|
||||||
|
if info.queue_flags.contains(vk::QueueFlags::GRAPHICS) {
|
||||||
|
Some(queue_family_index as u32)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let queue_family_index = match queue_family_index {
|
||||||
|
None => {
|
||||||
|
let msg =
|
||||||
|
CString::new(format!("Vulkan device has no graphics queue"))
|
||||||
|
.unwrap();
|
||||||
|
gfx_critical_note(msg.as_ptr());
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
Some(queue_family_index) => queue_family_index,
|
||||||
|
};
|
||||||
|
|
||||||
|
let family_info = vk::DeviceQueueCreateInfo::default()
|
||||||
|
.queue_family_index(queue_family_index)
|
||||||
|
.queue_priorities(&[1.0]);
|
||||||
|
let family_infos = [family_info];
|
||||||
|
|
||||||
|
let str_pointers = enabled_extensions
|
||||||
|
.iter()
|
||||||
|
.map(|&s| {
|
||||||
|
// Safe because `enabled_extensions` entries have static lifetime.
|
||||||
|
s.as_ptr()
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
let pre_info = vk::DeviceCreateInfo::default()
|
||||||
|
.queue_create_infos(&family_infos)
|
||||||
|
.enabled_extension_names(&str_pointers);
|
||||||
|
let info = enabled_phd_features.add_to_device_create(pre_info);
|
||||||
|
|
||||||
|
let raw_device =
|
||||||
|
match raw_instance.create_device(raw_physical_device, &info, None) {
|
||||||
|
Err(err) => {
|
||||||
|
let msg =
|
||||||
|
CString::new(format!("create_device() failed: {:?}", err))
|
||||||
|
.unwrap();
|
||||||
|
gfx_critical_note(msg.as_ptr());
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
Ok(raw_device) => raw_device,
|
||||||
|
};
|
||||||
|
|
||||||
|
let hal_device = hal_adapter.device_from_raw(
|
||||||
|
raw_device,
|
||||||
|
None,
|
||||||
|
&enabled_extensions,
|
||||||
|
desc.required_features,
|
||||||
|
&desc.memory_hints,
|
||||||
|
family_info.queue_family_index,
|
||||||
|
0,
|
||||||
|
);
|
||||||
|
Some(hal_device.unwrap())
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
let hal_device = match hal_device {
|
||||||
|
None => {
|
||||||
|
error_buf.init(ErrMsg {
|
||||||
|
message: "Failed to create ash::Device",
|
||||||
|
r#type: ErrorBufferType::Internal,
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Some(hal_device) => hal_device,
|
||||||
|
};
|
||||||
|
|
||||||
|
let res = global.create_device_from_hal(
|
||||||
|
self_id,
|
||||||
|
hal_device.into(),
|
||||||
|
&desc,
|
||||||
|
trace_path,
|
||||||
|
Some(new_device_id),
|
||||||
|
Some(new_queue_id),
|
||||||
|
);
|
||||||
|
if let Err(err) = res {
|
||||||
|
error_buf.init(err);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let res = global.adapter_request_device(
|
let res = global.adapter_request_device(
|
||||||
self_id,
|
self_id,
|
||||||
&desc,
|
&desc,
|
||||||
@ -649,37 +825,30 @@ pub struct DMABufInfo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
#[cfg(not(any(target_os = "macos", target_os = "ios")))]
|
||||||
pub struct VkImageHandle {
|
pub struct VkImageHandle {
|
||||||
//pub image: vk::Image,
|
pub device: vk::Device,
|
||||||
//pub memory: vk::DeviceMemory,
|
pub image: vk::Image,
|
||||||
|
pub memory: vk::DeviceMemory,
|
||||||
|
pub fn_destroy_image: vk::PFN_vkDestroyImage,
|
||||||
|
pub fn_free_memory: vk::PFN_vkFreeMemory,
|
||||||
pub memory_size: u64,
|
pub memory_size: u64,
|
||||||
pub memory_type_index: u32,
|
pub memory_type_index: u32,
|
||||||
pub modifier: u64,
|
pub modifier: u64,
|
||||||
//pub layouts: Vec<vk::SubresourceLayout>,
|
pub layouts: Vec<vk::SubresourceLayout>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(not(any(target_os = "macos", target_os = "ios")))]
|
||||||
impl VkImageHandle {
|
impl VkImageHandle {
|
||||||
pub fn new(
|
fn destroy(&self) {
|
||||||
//image: vk::Image,
|
unsafe {
|
||||||
//memory: vk::DeviceMemory,
|
(self.fn_destroy_image)(self.device, self.image, ptr::null());
|
||||||
memory_size: u64,
|
(self.fn_free_memory)(self.device, self.memory, ptr::null());
|
||||||
memory_type_index: u32,
|
|
||||||
modifier: u64,
|
|
||||||
//layouts: Vec<vk::SubresourceLayout>,
|
|
||||||
) -> VkImageHandle {
|
|
||||||
VkImageHandle {
|
|
||||||
//image,
|
|
||||||
//memory,
|
|
||||||
memory_size,
|
|
||||||
memory_type_index,
|
|
||||||
modifier,
|
|
||||||
//layouts,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
#[allow(unused_variables)]
|
|
||||||
#[cfg(not(any(target_os = "macos", target_os = "ios")))]
|
#[cfg(not(any(target_os = "macos", target_os = "ios")))]
|
||||||
pub extern "C" fn wgpu_vkimage_create_with_dma_buf(
|
pub extern "C" fn wgpu_vkimage_create_with_dma_buf(
|
||||||
global: &Global,
|
global: &Global,
|
||||||
@ -688,35 +857,309 @@ pub extern "C" fn wgpu_vkimage_create_with_dma_buf(
|
|||||||
height: u32,
|
height: u32,
|
||||||
out_memory_size: *mut u64,
|
out_memory_size: *mut u64,
|
||||||
) -> *mut VkImageHandle {
|
) -> *mut VkImageHandle {
|
||||||
|
let image_handle = unsafe {
|
||||||
|
global.device_as_hal::<wgc::api::Vulkan, _, Option<VkImageHandle>>(
|
||||||
|
device_id,
|
||||||
|
|hal_device| {
|
||||||
|
let hal_device = match hal_device {
|
||||||
|
None => {
|
||||||
|
let msg = CString::new(format!("Vulkan device is invalid")).unwrap();
|
||||||
|
gfx_critical_note(msg.as_ptr());
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
Some(hal_device) => hal_device,
|
||||||
|
};
|
||||||
|
|
||||||
|
let device = hal_device.raw_device();
|
||||||
|
let physical_device = hal_device.raw_physical_device();
|
||||||
|
let instance = hal_device.shared_instance().raw_instance();
|
||||||
|
|
||||||
|
let count = {
|
||||||
|
let mut drm_format_modifier_props_list =
|
||||||
|
vk::DrmFormatModifierPropertiesListEXT::default();
|
||||||
|
let mut format_properties_2 = vk::FormatProperties2::default()
|
||||||
|
.push_next(&mut drm_format_modifier_props_list);
|
||||||
|
|
||||||
|
instance.get_physical_device_format_properties2(
|
||||||
|
physical_device,
|
||||||
|
vk::Format::R8G8B8A8_UNORM,
|
||||||
|
&mut format_properties_2,
|
||||||
|
);
|
||||||
|
drm_format_modifier_props_list.drm_format_modifier_count
|
||||||
|
};
|
||||||
|
|
||||||
|
if count == 0 {
|
||||||
|
let msg =
|
||||||
|
CString::new(format!("get_physical_device_format_properties2() failed"))
|
||||||
|
.unwrap();
|
||||||
|
gfx_critical_note(msg.as_ptr());
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut modifier_props =
|
||||||
|
vec![vk::DrmFormatModifierPropertiesEXT::default(); count as usize];
|
||||||
|
|
||||||
|
let mut drm_format_modifier_props_list =
|
||||||
|
vk::DrmFormatModifierPropertiesListEXT::default()
|
||||||
|
.drm_format_modifier_properties(&mut modifier_props);
|
||||||
|
let mut format_properties_2 =
|
||||||
|
vk::FormatProperties2::default().push_next(&mut drm_format_modifier_props_list);
|
||||||
|
|
||||||
|
instance.get_physical_device_format_properties2(
|
||||||
|
physical_device,
|
||||||
|
vk::Format::R8G8B8A8_UNORM,
|
||||||
|
&mut format_properties_2,
|
||||||
|
);
|
||||||
|
|
||||||
|
let mut usage_flags = vk::ImageUsageFlags::empty();
|
||||||
|
usage_flags |= vk::ImageUsageFlags::COLOR_ATTACHMENT;
|
||||||
|
|
||||||
|
modifier_props.retain(|modifier_prop| {
|
||||||
|
let support = is_dmabuf_supported(
|
||||||
|
instance,
|
||||||
|
physical_device,
|
||||||
|
vk::Format::R8G8B8A8_UNORM,
|
||||||
|
modifier_prop.drm_format_modifier,
|
||||||
|
usage_flags,
|
||||||
|
);
|
||||||
|
support
|
||||||
|
});
|
||||||
|
|
||||||
|
if modifier_props.is_empty() {
|
||||||
|
let msg =
|
||||||
|
CString::new(format!("format not supported for dmabuf import")).unwrap();
|
||||||
|
gfx_critical_note(msg.as_ptr());
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let modifiers: Vec<u64> = modifier_props
|
||||||
|
.iter()
|
||||||
|
.map(|modifier_prop| modifier_prop.drm_format_modifier)
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let mut modifier_list = vk::ImageDrmFormatModifierListCreateInfoEXT::default()
|
||||||
|
.drm_format_modifiers(&modifiers);
|
||||||
|
|
||||||
|
let extent = vk::Extent3D {
|
||||||
|
width: width,
|
||||||
|
height: height,
|
||||||
|
depth: 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut external_image_create_info = vk::ExternalMemoryImageCreateInfo::default()
|
||||||
|
.handle_types(vk::ExternalMemoryHandleTypeFlags::DMA_BUF_EXT);
|
||||||
|
|
||||||
|
let mut export_memory_alloc_info = vk::ExportMemoryAllocateInfo::default()
|
||||||
|
.handle_types(vk::ExternalMemoryHandleTypeFlags::DMA_BUF_EXT);
|
||||||
|
|
||||||
|
let flags = vk::ImageCreateFlags::empty();
|
||||||
|
|
||||||
|
let vk_info = vk::ImageCreateInfo::default()
|
||||||
|
.flags(flags)
|
||||||
|
.image_type(vk::ImageType::TYPE_2D)
|
||||||
|
.format(vk::Format::R8G8B8A8_UNORM)
|
||||||
|
.extent(extent)
|
||||||
|
.mip_levels(1)
|
||||||
|
.array_layers(1)
|
||||||
|
.samples(vk::SampleCountFlags::TYPE_1)
|
||||||
|
.tiling(vk::ImageTiling::DRM_FORMAT_MODIFIER_EXT)
|
||||||
|
.usage(usage_flags)
|
||||||
|
.sharing_mode(vk::SharingMode::EXCLUSIVE)
|
||||||
|
.initial_layout(vk::ImageLayout::UNDEFINED)
|
||||||
|
.push_next(&mut modifier_list)
|
||||||
|
.push_next(&mut external_image_create_info);
|
||||||
|
|
||||||
|
let image = match device.create_image(&vk_info, None) {
|
||||||
|
Err(err) => {
|
||||||
|
let msg =
|
||||||
|
CString::new(format!("create_image() failed: {:?}", err)).unwrap();
|
||||||
|
gfx_critical_note(msg.as_ptr());
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
Ok(image) => image,
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut image_modifier_properties =
|
||||||
|
vk::ImageDrmFormatModifierPropertiesEXT::default();
|
||||||
|
let image_drm_format_modifier =
|
||||||
|
ash::ext::image_drm_format_modifier::Device::new(instance, device);
|
||||||
|
let ret = image_drm_format_modifier.get_image_drm_format_modifier_properties(
|
||||||
|
image,
|
||||||
|
&mut image_modifier_properties,
|
||||||
|
);
|
||||||
|
if ret.is_err() {
|
||||||
|
let msg = CString::new(format!(
|
||||||
|
"get_image_drm_format_modifier_properties() failed: {:?}",
|
||||||
|
ret
|
||||||
|
))
|
||||||
|
.unwrap();
|
||||||
|
gfx_critical_note(msg.as_ptr());
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let memory_req = device.get_image_memory_requirements(image);
|
||||||
|
|
||||||
|
let mem_properties =
|
||||||
|
instance.get_physical_device_memory_properties(physical_device);
|
||||||
|
|
||||||
|
let index = mem_properties
|
||||||
|
.memory_types
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.position(|(i, t)| {
|
||||||
|
((1 << i) & memory_req.memory_type_bits) != 0
|
||||||
|
&& t.property_flags
|
||||||
|
.contains(vk::MemoryPropertyFlags::DEVICE_LOCAL)
|
||||||
|
});
|
||||||
|
|
||||||
|
let index = match index {
|
||||||
|
None => {
|
||||||
|
let msg = CString::new(format!("Failed to get DEVICE_LOCAL memory index"))
|
||||||
|
.unwrap();
|
||||||
|
gfx_critical_note(msg.as_ptr());
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
Some(index) => index,
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut dedicated_memory_info =
|
||||||
|
vk::MemoryDedicatedAllocateInfo::default().image(image);
|
||||||
|
|
||||||
|
let memory_allocate_info = vk::MemoryAllocateInfo::default()
|
||||||
|
.allocation_size(memory_req.size)
|
||||||
|
.memory_type_index(index as u32)
|
||||||
|
.push_next(&mut dedicated_memory_info)
|
||||||
|
.push_next(&mut export_memory_alloc_info);
|
||||||
|
|
||||||
|
let memory = match device.allocate_memory(&memory_allocate_info, None) {
|
||||||
|
Err(err) => {
|
||||||
|
let msg =
|
||||||
|
CString::new(format!("allocate_memory() failed: {:?}", err)).unwrap();
|
||||||
|
gfx_critical_note(msg.as_ptr());
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
Ok(memory) => memory,
|
||||||
|
};
|
||||||
|
|
||||||
|
let result = device.bind_image_memory(image, memory, /* offset */ 0);
|
||||||
|
if result.is_err() {
|
||||||
|
let msg =
|
||||||
|
CString::new(format!("bind_image_memory() failed: {:?}", result)).unwrap();
|
||||||
|
gfx_critical_note(msg.as_ptr());
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
*out_memory_size = memory_req.size;
|
||||||
|
|
||||||
|
let modifier_prop = modifier_props.iter().find(|prop| {
|
||||||
|
prop.drm_format_modifier == image_modifier_properties.drm_format_modifier
|
||||||
|
});
|
||||||
|
let modifier_prop = match modifier_prop {
|
||||||
|
None => {
|
||||||
|
let msg = CString::new(format!("failed to find modifier_prop")).unwrap();
|
||||||
|
gfx_critical_note(msg.as_ptr());
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
Some(modifier_prop) => modifier_prop,
|
||||||
|
};
|
||||||
|
|
||||||
|
let plane_count = modifier_prop.drm_format_modifier_plane_count;
|
||||||
|
|
||||||
|
let mut layouts = Vec::new();
|
||||||
|
for i in 0..plane_count {
|
||||||
|
let flag = match i {
|
||||||
|
0 => vk::ImageAspectFlags::PLANE_0,
|
||||||
|
1 => vk::ImageAspectFlags::PLANE_1,
|
||||||
|
2 => vk::ImageAspectFlags::PLANE_2,
|
||||||
|
_ => unreachable!(),
|
||||||
|
};
|
||||||
|
let subresource = vk::ImageSubresource::default().aspect_mask(flag);
|
||||||
|
let layout = device.get_image_subresource_layout(image, subresource);
|
||||||
|
layouts.push(layout);
|
||||||
|
}
|
||||||
|
|
||||||
|
Some(VkImageHandle {
|
||||||
|
device: device.handle(),
|
||||||
|
image: image,
|
||||||
|
memory: memory,
|
||||||
|
fn_destroy_image: device.fp_v1_0().destroy_image,
|
||||||
|
fn_free_memory: device.fp_v1_0().free_memory,
|
||||||
|
memory_size: memory_req.size,
|
||||||
|
memory_type_index: index as u32,
|
||||||
|
modifier: image_modifier_properties.drm_format_modifier,
|
||||||
|
layouts,
|
||||||
|
})
|
||||||
|
},
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
let image_handle = match image_handle {
|
||||||
|
None => {
|
||||||
return ptr::null_mut();
|
return ptr::null_mut();
|
||||||
|
}
|
||||||
|
Some(image_handle) => image_handle,
|
||||||
|
};
|
||||||
|
|
||||||
|
Box::into_raw(Box::new(image_handle))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
|
#[cfg(not(any(target_os = "macos", target_os = "ios")))]
|
||||||
pub unsafe extern "C" fn wgpu_vkimage_delete(handle: *mut VkImageHandle) {
|
pub unsafe extern "C" fn wgpu_vkimage_delete(handle: *mut VkImageHandle) {
|
||||||
let _ = Box::from_raw(handle);
|
let handle = Box::from_raw(handle);
|
||||||
|
handle.destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
#[allow(unused_variables)]
|
|
||||||
#[cfg(not(any(target_os = "macos", target_os = "ios")))]
|
#[cfg(not(any(target_os = "macos", target_os = "ios")))]
|
||||||
pub extern "C" fn wgpu_vkimage_get_file_descriptor(
|
pub extern "C" fn wgpu_vkimage_get_file_descriptor(
|
||||||
global: &Global,
|
global: &Global,
|
||||||
device_id: id::DeviceId,
|
device_id: id::DeviceId,
|
||||||
handle: &VkImageHandle,
|
handle: &VkImageHandle,
|
||||||
) -> i32 {
|
) -> i32 {
|
||||||
-1
|
unsafe {
|
||||||
|
global.device_as_hal::<wgc::api::Vulkan, _, i32>(device_id, |hal_device| {
|
||||||
|
let hal_device = match hal_device {
|
||||||
|
None => {
|
||||||
|
let msg = CString::new(format!("Vulkan device is invalid")).unwrap();
|
||||||
|
gfx_critical_note(msg.as_ptr());
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
Some(hal_device) => hal_device,
|
||||||
|
};
|
||||||
|
|
||||||
|
let device = hal_device.raw_device();
|
||||||
|
let instance = hal_device.shared_instance().raw_instance();
|
||||||
|
|
||||||
|
let get_fd_info = vk::MemoryGetFdInfoKHR::default()
|
||||||
|
.memory(handle.memory)
|
||||||
|
.handle_type(vk::ExternalMemoryHandleTypeFlags::DMA_BUF_EXT);
|
||||||
|
|
||||||
|
let loader = khr::external_memory_fd::Device::new(instance, device);
|
||||||
|
|
||||||
|
return match loader.get_memory_fd(&get_fd_info) {
|
||||||
|
Err(..) => -1,
|
||||||
|
Ok(fd) => fd,
|
||||||
|
};
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
#[allow(unused_variables)]
|
#[cfg(not(any(target_os = "macos", target_os = "ios")))]
|
||||||
pub extern "C" fn wgpu_vkimage_get_dma_buf_info(handle: &VkImageHandle) -> DMABufInfo {
|
pub extern "C" fn wgpu_vkimage_get_dma_buf_info(handle: &VkImageHandle) -> DMABufInfo {
|
||||||
let offsets: [u64; 3] = [0; 3];
|
let mut offsets: [u64; 3] = [0; 3];
|
||||||
let strides: [u64; 3] = [0; 3];
|
let mut strides: [u64; 3] = [0; 3];
|
||||||
|
let plane_count = handle.layouts.len();
|
||||||
|
for i in 0..plane_count {
|
||||||
|
offsets[i] = handle.layouts[i].offset;
|
||||||
|
strides[i] = handle.layouts[i].row_pitch;
|
||||||
|
}
|
||||||
|
|
||||||
DMABufInfo {
|
DMABufInfo {
|
||||||
is_valid: false,
|
is_valid: true,
|
||||||
modifier: 0,
|
modifier: handle.modifier,
|
||||||
plane_count: 0,
|
plane_count: plane_count as u32,
|
||||||
offsets,
|
offsets,
|
||||||
strides,
|
strides,
|
||||||
}
|
}
|
||||||
@ -753,6 +1196,7 @@ extern "C" {
|
|||||||
) -> *mut c_void;
|
) -> *mut c_void;
|
||||||
#[allow(improper_ctypes)]
|
#[allow(improper_ctypes)]
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
|
#[cfg(not(any(target_os = "macos", target_os = "ios")))]
|
||||||
fn wgpu_server_get_vk_image_handle(
|
fn wgpu_server_get_vk_image_handle(
|
||||||
param: *mut c_void,
|
param: *mut c_void,
|
||||||
texture_id: id::TextureId,
|
texture_id: id::TextureId,
|
||||||
@ -761,6 +1205,93 @@ extern "C" {
|
|||||||
fn wgpu_server_get_dma_buf_fd(param: *mut c_void, id: id::TextureId) -> i32;
|
fn wgpu_server_get_dma_buf_fd(param: *mut c_void, id: id::TextureId) -> i32;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(not(any(target_os = "macos", target_os = "ios")))]
|
||||||
|
pub unsafe fn is_dmabuf_supported(
|
||||||
|
instance: &ash::Instance,
|
||||||
|
physical_device: vk::PhysicalDevice,
|
||||||
|
format: vk::Format,
|
||||||
|
modifier: u64,
|
||||||
|
usage: vk::ImageUsageFlags,
|
||||||
|
) -> bool {
|
||||||
|
let mut drm_props = vk::ExternalImageFormatProperties::default();
|
||||||
|
let mut props = vk::ImageFormatProperties2::default().push_next(&mut drm_props);
|
||||||
|
|
||||||
|
let mut modifier_info =
|
||||||
|
vk::PhysicalDeviceImageDrmFormatModifierInfoEXT::default().drm_format_modifier(modifier);
|
||||||
|
|
||||||
|
let mut external_format_info = vk::PhysicalDeviceExternalImageFormatInfo::default()
|
||||||
|
.handle_type(vk::ExternalMemoryHandleTypeFlags::DMA_BUF_EXT);
|
||||||
|
|
||||||
|
let format_info = vk::PhysicalDeviceImageFormatInfo2::default()
|
||||||
|
.format(format)
|
||||||
|
.ty(vk::ImageType::TYPE_2D)
|
||||||
|
.usage(usage)
|
||||||
|
.tiling(vk::ImageTiling::DRM_FORMAT_MODIFIER_EXT)
|
||||||
|
.push_next(&mut external_format_info)
|
||||||
|
.push_next(&mut modifier_info);
|
||||||
|
|
||||||
|
match instance.get_physical_device_image_format_properties2(
|
||||||
|
physical_device,
|
||||||
|
&format_info,
|
||||||
|
&mut props,
|
||||||
|
) {
|
||||||
|
Ok(_) => (),
|
||||||
|
Err(_) => {
|
||||||
|
//debug!(?format, ?modifier, "format not supported for dma import");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
drm_props
|
||||||
|
.external_memory_properties
|
||||||
|
.compatible_handle_types
|
||||||
|
.contains(vk::ExternalMemoryHandleTypeFlags::DMA_BUF_EXT)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(any(target_os = "macos", target_os = "ios")))]
|
||||||
|
pub fn select_memory_type(
|
||||||
|
props: &vk::PhysicalDeviceMemoryProperties,
|
||||||
|
flags: vk::MemoryPropertyFlags,
|
||||||
|
memory_type_bits: Option<u32>,
|
||||||
|
) -> Option<u32> {
|
||||||
|
for i in 0..props.memory_type_count {
|
||||||
|
if let Some(mask) = memory_type_bits {
|
||||||
|
if mask & (1 << i) == 0 {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if flags.is_empty()
|
||||||
|
|| props.memory_types[i as usize]
|
||||||
|
.property_flags
|
||||||
|
.contains(flags)
|
||||||
|
{
|
||||||
|
return Some(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(any(target_os = "windows", target_os = "macos", target_os = "ios")))]
|
||||||
|
struct VkImageHolder {
|
||||||
|
pub device: vk::Device,
|
||||||
|
pub image: vk::Image,
|
||||||
|
pub memory: vk::DeviceMemory,
|
||||||
|
pub fn_destroy_image: vk::PFN_vkDestroyImage,
|
||||||
|
pub fn_free_memory: vk::PFN_vkFreeMemory,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(any(target_os = "windows", target_os = "macos", target_os = "ios")))]
|
||||||
|
impl VkImageHolder {
|
||||||
|
fn destroy(&self) {
|
||||||
|
unsafe {
|
||||||
|
(self.fn_destroy_image)(self.device, self.image, ptr::null());
|
||||||
|
(self.fn_free_memory)(self.device, self.memory, ptr::null());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Global {
|
impl Global {
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
fn create_texture_with_external_texture_d3d11(
|
fn create_texture_with_external_texture_d3d11(
|
||||||
@ -854,6 +1385,207 @@ impl Global {
|
|||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
#[cfg(not(any(target_os = "windows", target_os = "macos", target_os = "ios")))]
|
||||||
|
fn create_texture_with_external_texture_dmabuf(
|
||||||
|
&self,
|
||||||
|
device_id: id::DeviceId,
|
||||||
|
texture_id: id::TextureId,
|
||||||
|
desc: &wgc::resource::TextureDescriptor,
|
||||||
|
swap_chain_id: Option<SwapChainId>,
|
||||||
|
) -> bool {
|
||||||
|
let ret = unsafe {
|
||||||
|
wgpu_server_ensure_external_texture_for_swap_chain(
|
||||||
|
self.owner,
|
||||||
|
swap_chain_id.unwrap(),
|
||||||
|
device_id,
|
||||||
|
texture_id,
|
||||||
|
desc.size.width,
|
||||||
|
desc.size.height,
|
||||||
|
desc.format,
|
||||||
|
desc.usage,
|
||||||
|
)
|
||||||
|
};
|
||||||
|
if ret != true {
|
||||||
|
let msg = CString::new(format!("Failed to create external texture")).unwrap();
|
||||||
|
unsafe {
|
||||||
|
gfx_critical_note(msg.as_ptr());
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
let handle = unsafe { wgpu_server_get_vk_image_handle(self.owner, texture_id) };
|
||||||
|
if handle.is_null() {
|
||||||
|
let msg = CString::new(format!("Failed to get VkImageHandle")).unwrap();
|
||||||
|
unsafe {
|
||||||
|
gfx_critical_note(msg.as_ptr());
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
let vk_image_wrapper = unsafe { &*handle };
|
||||||
|
|
||||||
|
let fd = unsafe { wgpu_server_get_dma_buf_fd(self.owner, texture_id) };
|
||||||
|
if fd < 0 {
|
||||||
|
let msg = CString::new(format!("Failed to get DMABuf fd")).unwrap();
|
||||||
|
unsafe {
|
||||||
|
gfx_critical_note(msg.as_ptr());
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure to close file descriptor
|
||||||
|
let owned_fd = unsafe { OwnedFd::from_raw_fd(fd as RawFd) };
|
||||||
|
|
||||||
|
let image_holder = unsafe {
|
||||||
|
self.device_as_hal::<wgc::api::Vulkan, _, Option<VkImageHolder>>(
|
||||||
|
device_id,
|
||||||
|
|hal_device| {
|
||||||
|
let hal_device = match hal_device {
|
||||||
|
None => {
|
||||||
|
let msg = CString::new(format!("Vulkan device is invalid")).unwrap();
|
||||||
|
gfx_critical_note(msg.as_ptr());
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
Some(hal_device) => hal_device,
|
||||||
|
};
|
||||||
|
|
||||||
|
let device = hal_device.raw_device();
|
||||||
|
|
||||||
|
let extent = vk::Extent3D {
|
||||||
|
width: desc.size.width,
|
||||||
|
height: desc.size.height,
|
||||||
|
depth: 1,
|
||||||
|
};
|
||||||
|
let mut usage_flags = vk::ImageUsageFlags::empty();
|
||||||
|
usage_flags |= vk::ImageUsageFlags::COLOR_ATTACHMENT;
|
||||||
|
|
||||||
|
let mut external_image_create_info =
|
||||||
|
vk::ExternalMemoryImageCreateInfo::default()
|
||||||
|
.handle_types(vk::ExternalMemoryHandleTypeFlags::DMA_BUF_EXT);
|
||||||
|
|
||||||
|
let vk_info = vk::ImageCreateInfo::default()
|
||||||
|
.flags(vk::ImageCreateFlags::ALIAS)
|
||||||
|
.image_type(vk::ImageType::TYPE_2D)
|
||||||
|
.format(vk::Format::R8G8B8A8_UNORM)
|
||||||
|
.extent(extent)
|
||||||
|
.mip_levels(1)
|
||||||
|
.array_layers(1)
|
||||||
|
.samples(vk::SampleCountFlags::TYPE_1)
|
||||||
|
.tiling(vk::ImageTiling::OPTIMAL)
|
||||||
|
.usage(usage_flags)
|
||||||
|
.sharing_mode(vk::SharingMode::EXCLUSIVE)
|
||||||
|
.initial_layout(vk::ImageLayout::UNDEFINED)
|
||||||
|
.push_next(&mut external_image_create_info);
|
||||||
|
|
||||||
|
let image = match device.create_image(&vk_info, None) {
|
||||||
|
Err(err) => {
|
||||||
|
let msg =
|
||||||
|
CString::new(format!("create_image() failed: {:?}", err)).unwrap();
|
||||||
|
gfx_critical_note(msg.as_ptr());
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
Ok(image) => image,
|
||||||
|
};
|
||||||
|
|
||||||
|
let memory_req = device.get_image_memory_requirements(image);
|
||||||
|
if memory_req.size > vk_image_wrapper.memory_size {
|
||||||
|
let msg = CString::new(format!("Invalid memory size")).unwrap();
|
||||||
|
gfx_critical_note(msg.as_ptr());
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut dedicated_memory_info =
|
||||||
|
vk::MemoryDedicatedAllocateInfo::default().image(image);
|
||||||
|
|
||||||
|
let mut import_memory_fd_info = vk::ImportMemoryFdInfoKHR::default()
|
||||||
|
.handle_type(vk::ExternalMemoryHandleTypeFlags::DMA_BUF_EXT)
|
||||||
|
.fd(owned_fd.into_raw_fd());
|
||||||
|
|
||||||
|
let memory_allocate_info = vk::MemoryAllocateInfo::default()
|
||||||
|
.allocation_size(vk_image_wrapper.memory_size)
|
||||||
|
.memory_type_index(vk_image_wrapper.memory_type_index)
|
||||||
|
.push_next(&mut dedicated_memory_info)
|
||||||
|
.push_next(&mut import_memory_fd_info);
|
||||||
|
|
||||||
|
let memory = match device.allocate_memory(&memory_allocate_info, None) {
|
||||||
|
Err(err) => {
|
||||||
|
let msg = CString::new(format!("allocate_memory() failed: {:?}", err))
|
||||||
|
.unwrap();
|
||||||
|
gfx_critical_note(msg.as_ptr());
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
Ok(memory) => memory,
|
||||||
|
};
|
||||||
|
|
||||||
|
let result = device.bind_image_memory(image, memory, /* offset */ 0);
|
||||||
|
if result.is_err() {
|
||||||
|
let msg = CString::new(format!("bind_image_memory() failed: {:?}", result))
|
||||||
|
.unwrap();
|
||||||
|
gfx_critical_note(msg.as_ptr());
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
Some(VkImageHolder {
|
||||||
|
device: device.handle(),
|
||||||
|
image: image,
|
||||||
|
memory: memory,
|
||||||
|
fn_destroy_image: device.fp_v1_0().destroy_image,
|
||||||
|
fn_free_memory: device.fp_v1_0().free_memory,
|
||||||
|
})
|
||||||
|
},
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
let image_holder = match image_holder {
|
||||||
|
None => {
|
||||||
|
let msg = CString::new(format!("Failed to get vk::Image")).unwrap();
|
||||||
|
unsafe {
|
||||||
|
gfx_critical_note(msg.as_ptr());
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Some(image_holder) => image_holder,
|
||||||
|
};
|
||||||
|
|
||||||
|
let hal_desc = wgh::TextureDescriptor {
|
||||||
|
label: None,
|
||||||
|
size: desc.size,
|
||||||
|
mip_level_count: desc.mip_level_count,
|
||||||
|
sample_count: desc.sample_count,
|
||||||
|
dimension: desc.dimension,
|
||||||
|
format: desc.format,
|
||||||
|
usage: wgh::TextureUses::COPY_DST | wgh::TextureUses::COLOR_TARGET,
|
||||||
|
memory_flags: wgh::MemoryFlags::empty(),
|
||||||
|
view_formats: vec![],
|
||||||
|
};
|
||||||
|
|
||||||
|
let image = image_holder.image;
|
||||||
|
|
||||||
|
let hal_texture = unsafe {
|
||||||
|
<wgh::api::Vulkan as wgh::Api>::Device::texture_from_raw(
|
||||||
|
image,
|
||||||
|
&hal_desc,
|
||||||
|
Some(Box::new(move || {
|
||||||
|
image_holder.destroy();
|
||||||
|
})),
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
let (_, error) = unsafe {
|
||||||
|
self.create_texture_from_hal(Box::new(hal_texture), device_id, &desc, Some(texture_id))
|
||||||
|
};
|
||||||
|
if let Some(err) = error {
|
||||||
|
let msg = CString::new(format!("create_texture_from_hal() failed: {:?}", err)).unwrap();
|
||||||
|
unsafe {
|
||||||
|
gfx_critical_note(msg.as_ptr());
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
fn device_action(
|
fn device_action(
|
||||||
&self,
|
&self,
|
||||||
self_id: id::DeviceId,
|
self_id: id::DeviceId,
|
||||||
@ -876,13 +1608,8 @@ impl Global {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let use_external_texture = if swap_chain_id.is_some() {
|
let use_external_texture = if let Some(id) = swap_chain_id {
|
||||||
unsafe {
|
unsafe { wgpu_server_use_external_texture_for_swap_chain(self.owner, id) }
|
||||||
wgpu_server_use_external_texture_for_swap_chain(
|
|
||||||
self.owner,
|
|
||||||
swap_chain_id.unwrap(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
};
|
};
|
||||||
@ -900,6 +1627,20 @@ impl Global {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
{
|
||||||
|
let is_created = self.create_texture_with_external_texture_dmabuf(
|
||||||
|
self_id,
|
||||||
|
id,
|
||||||
|
&desc,
|
||||||
|
swap_chain_id,
|
||||||
|
);
|
||||||
|
if is_created {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
wgpu_server_disable_external_texture_for_swap_chain(
|
wgpu_server_disable_external_texture_for_swap_chain(
|
||||||
self.owner,
|
self.owner,
|
||||||
|
@ -58,6 +58,7 @@ class DefaultDelete<webgpu::ffi::WGPUGlobal> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#if !defined(XP_MACOSX)
|
||||||
template <>
|
template <>
|
||||||
class DefaultDelete<webgpu::ffi::WGPUVkImageHandle> {
|
class DefaultDelete<webgpu::ffi::WGPUVkImageHandle> {
|
||||||
public:
|
public:
|
||||||
@ -65,6 +66,7 @@ class DefaultDelete<webgpu::ffi::WGPUVkImageHandle> {
|
|||||||
webgpu::ffi::wgpu_vkimage_delete(aPtr);
|
webgpu::ffi::wgpu_vkimage_delete(aPtr);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user