ALVR-IPv6/alvr/experiments/server_compositor/src/convert.rs

142 lines
4.8 KiB
Rust

use super::{Compositor, Swapchain, TextureType};
use alvr_common::prelude::*;
use openxr_sys as sys;
use wgpu::{Extent3d, TextureDescriptor, TextureDimension, TextureFormat, TextureUsages};
use wgpu_hal as hal;
pub enum SwapchainCreateData {
// Used for the Vulkan layer
#[cfg(target_os = "linux")]
External {
images: Vec<vk::Image>,
vk_usage: vk::ImageUsageFlags,
vk_format: vk::Format,
hal_usage: hal::TextureUses,
},
// Used for the Windows OpenVR driver (Some) or for a OpenXR runtime (None)
Count(Option<usize>),
}
pub struct SwapchainCreateInfo {
usage: sys::SwapchainUsageFlags,
format: TextureFormat,
sample_count: u32,
width: u32,
height: u32,
texture_type: TextureType,
mip_count: u32,
}
impl Compositor {
// corresponds to xrCreateSwapchain
pub fn create_swapchain(
&self,
data: SwapchainCreateData,
info: SwapchainCreateInfo,
) -> StrResult<Swapchain> {
let wgpu_usage = {
let mut wgpu_usage = TextureUsages::TEXTURE_BINDING; // Always required
if info
.usage
.contains(sys::SwapchainUsageFlags::COLOR_ATTACHMENT)
{
wgpu_usage |= TextureUsages::RENDER_ATTACHMENT;
}
if info
.usage
.contains(sys::SwapchainUsageFlags::DEPTH_STENCIL_ATTACHMENT)
{
wgpu_usage |= TextureUsages::RENDER_ATTACHMENT;
}
if info.usage.contains(sys::SwapchainUsageFlags::TRANSFER_SRC) {
wgpu_usage |= TextureUsages::COPY_SRC;
}
if info.usage.contains(sys::SwapchainUsageFlags::TRANSFER_DST) {
wgpu_usage |= TextureUsages::COPY_DST;
}
// Unused flags:
// * UNORDERED_ACCESS: No-op on vulkan
// * SAMPLED: Already required
// * MUTABLE_FORMAT: wgpu does not support this, but it should be no-op for the internal
// Vulkan images (todo: check)
// * INPUT_ATTACHMENT: Always enabled on wgpu (todo: check)
wgpu_usage
};
let depth_or_array_layers = match info.texture_type {
TextureType::D2 { array_size } => array_size,
TextureType::Cubemap => 6,
};
let texture_descriptor = TextureDescriptor {
label: None,
size: Extent3d {
width: info.width,
height: info.height,
depth_or_array_layers,
},
mip_level_count: info.mip_count,
sample_count: info.sample_count,
dimension: TextureDimension::D2,
format: info.format,
usage: wgpu_usage,
};
let textures = match data {
#[cfg(target_os = "linux")]
SwapchainCreateData::External {
images,
vk_usage,
vk_format,
hal_usage,
} => images
.into_iter()
.map(|vk_image| {
let hal_texture = unsafe {
<hal::api::Vulkan as hal::Api>::Device::texture_from_raw(
vk_image,
&hal::TextureDescriptor {
label: None,
size: Extent3d {
width,
height,
depth_or_array_layers: array_size,
},
mip_level_count: mip_count,
sample_count,
dimension: TextureDimension::D2,
format,
usage: hal_usage,
memory_flags: hal::MemoryFlags::empty(),
},
None,
)
};
unsafe {
self.context
.device
.create_texture_from_hal::<hal::api::Vulkan>(
hal_texture,
&texture_descriptor,
)
}
})
.collect(),
SwapchainCreateData::Count(count) => (0..count.unwrap_or(2))
.map(|_| self.context.device().create_texture(&texture_descriptor))
.collect(),
};
let array_size = match info.texture_type {
TextureType::D2 { array_size } => array_size,
TextureType::Cubemap => 1,
};
Ok(self.inner_create_swapchain(textures, array_size))
}
}