on the right path
This commit is contained in:
@@ -30,9 +30,9 @@ pub mod overlay;
|
|||||||
pub fn openvr_run() {
|
pub fn openvr_run() {
|
||||||
let app_type = EVRApplicationType::VRApplication_Overlay;
|
let app_type = EVRApplicationType::VRApplication_Overlay;
|
||||||
let Ok(context) = ovr_overlay::Context::init(app_type) else {
|
let Ok(context) = ovr_overlay::Context::init(app_type) else {
|
||||||
error!("Failed to initialize OpenVR");
|
error!("Failed to initialize OpenVR");
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut overlay_mngr = context.overlay_mngr();
|
let mut overlay_mngr = context.overlay_mngr();
|
||||||
//let mut settings_mngr = context.settings_mngr();
|
//let mut settings_mngr = context.settings_mngr();
|
||||||
@@ -65,11 +65,16 @@ pub fn openvr_run() {
|
|||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
let Ok(refresh_rate) = system_mngr.get_tracked_device_property::<f32>(TrackedDeviceIndex::HMD, ETrackedDeviceProperty::Prop_DisplayFrequency_Float) else {
|
let Ok(refresh_rate) = system_mngr.get_tracked_device_property::<f32>(
|
||||||
|
TrackedDeviceIndex::HMD,
|
||||||
|
ETrackedDeviceProperty::Prop_DisplayFrequency_Float,
|
||||||
|
) else {
|
||||||
error!("Failed to get display refresh rate");
|
error!("Failed to get display refresh rate");
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
info!("HMD running @ {} Hz", refresh_rate);
|
||||||
|
|
||||||
let frame_time = (1000.0 / refresh_rate).floor() * 0.001;
|
let frame_time = (1000.0 / refresh_rate).floor() * 0.001;
|
||||||
let mut next_device_update = Instant::now();
|
let mut next_device_update = Instant::now();
|
||||||
let mut due_tasks = VecDeque::with_capacity(4);
|
let mut due_tasks = VecDeque::with_capacity(4);
|
||||||
@@ -141,7 +146,7 @@ pub fn openvr_run() {
|
|||||||
let mut seconds_since_vsync = 0f32;
|
let mut seconds_since_vsync = 0f32;
|
||||||
std::thread::sleep(Duration::from_secs_f32(
|
std::thread::sleep(Duration::from_secs_f32(
|
||||||
if system_mngr.get_time_since_last_vsync(&mut seconds_since_vsync, &mut 0u64) {
|
if system_mngr.get_time_since_last_vsync(&mut seconds_since_vsync, &mut 0u64) {
|
||||||
frame_time - seconds_since_vsync
|
(frame_time - seconds_since_vsync).max(0.0)
|
||||||
} else {
|
} else {
|
||||||
0.011
|
0.011
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,19 +1,10 @@
|
|||||||
use glam::Vec4;
|
use glam::Vec4;
|
||||||
use ovr_overlay::{
|
use ovr_overlay::{
|
||||||
overlay::{OverlayHandle, OverlayManager},
|
overlay::{OverlayHandle, OverlayManager},
|
||||||
sys::VRVulkanTextureData_t,
|
pose::Matrix3x4,
|
||||||
};
|
sys::{ETrackingUniverseOrigin, VRVulkanTextureData_t},
|
||||||
use vulkano::{
|
|
||||||
command_buffer::{
|
|
||||||
synced::{
|
|
||||||
SyncCommandBuffer, SyncCommandBufferBuilder, SyncCommandBufferBuilderExecuteCommands,
|
|
||||||
},
|
|
||||||
AutoCommandBufferBuilder, CommandBufferExecFuture,
|
|
||||||
},
|
|
||||||
image::{ImageAccess, ImageLayout},
|
|
||||||
sync::{future::NowFuture, ImageMemoryBarrier},
|
|
||||||
Handle, VulkanObject,
|
|
||||||
};
|
};
|
||||||
|
use vulkano::{image::ImageAccess, Handle, VulkanObject};
|
||||||
|
|
||||||
use crate::{backend::overlay::OverlayData, graphics::WlxGraphics, state::AppState};
|
use crate::{backend::overlay::OverlayData, graphics::WlxGraphics, state::AppState};
|
||||||
|
|
||||||
@@ -43,6 +34,7 @@ impl OverlayData<OpenVrOverlayData> {
|
|||||||
log::debug!("{}: initialize", self.state.name);
|
log::debug!("{}: initialize", self.state.name);
|
||||||
|
|
||||||
self.data.handle = Some(handle);
|
self.data.handle = Some(handle);
|
||||||
|
self.data.color = Vec4::ONE;
|
||||||
|
|
||||||
self.init(app);
|
self.init(app);
|
||||||
|
|
||||||
@@ -63,6 +55,7 @@ impl OverlayData<OpenVrOverlayData> {
|
|||||||
|
|
||||||
pub fn after_render(&mut self, overlay: &mut OverlayManager, graphics: &WlxGraphics) {
|
pub fn after_render(&mut self, overlay: &mut OverlayManager, graphics: &WlxGraphics) {
|
||||||
if self.data.visible {
|
if self.data.visible {
|
||||||
|
self.upload_transform(overlay);
|
||||||
self.upload_texture(overlay, graphics);
|
self.upload_texture(overlay, graphics);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -104,7 +97,7 @@ impl OverlayData<OpenVrOverlayData> {
|
|||||||
r: self.data.color.x,
|
r: self.data.color.x,
|
||||||
g: self.data.color.y,
|
g: self.data.color.y,
|
||||||
b: self.data.color.z,
|
b: self.data.color.z,
|
||||||
a: 1.0,
|
a: self.data.color.w,
|
||||||
},
|
},
|
||||||
) {
|
) {
|
||||||
panic!("Failed to set overlay tint: {}", e);
|
panic!("Failed to set overlay tint: {}", e);
|
||||||
@@ -141,6 +134,42 @@ impl OverlayData<OpenVrOverlayData> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn upload_transform(&self, overlay: &mut OverlayManager) {
|
||||||
|
let Some(handle) = self.data.handle else {
|
||||||
|
log::debug!("{}: No overlay handle", self.state.name);
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
let transform = Matrix3x4([
|
||||||
|
[
|
||||||
|
self.state.transform.matrix3.x_axis.x,
|
||||||
|
self.state.transform.matrix3.y_axis.x,
|
||||||
|
self.state.transform.matrix3.z_axis.x,
|
||||||
|
self.state.transform.translation.x,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
self.state.transform.matrix3.x_axis.y,
|
||||||
|
self.state.transform.matrix3.y_axis.y,
|
||||||
|
self.state.transform.matrix3.z_axis.y,
|
||||||
|
self.state.transform.translation.y,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
self.state.transform.matrix3.x_axis.z,
|
||||||
|
self.state.transform.matrix3.y_axis.z,
|
||||||
|
self.state.transform.matrix3.z_axis.z,
|
||||||
|
self.state.transform.translation.z,
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
|
||||||
|
if let Err(e) = overlay.set_transform_absolute(
|
||||||
|
handle,
|
||||||
|
ETrackingUniverseOrigin::TrackingUniverseStanding,
|
||||||
|
&transform,
|
||||||
|
) {
|
||||||
|
panic!("Failed to set overlay transform: {}", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn upload_texture(&mut self, overlay: &mut OverlayManager, graphics: &WlxGraphics) {
|
fn upload_texture(&mut self, overlay: &mut OverlayManager, graphics: &WlxGraphics) {
|
||||||
let Some(handle) = self.data.handle else {
|
let Some(handle) = self.data.handle else {
|
||||||
log::debug!("{}: No overlay handle", self.state.name);
|
log::debug!("{}: No overlay handle", self.state.name);
|
||||||
@@ -181,27 +210,10 @@ impl OverlayData<OpenVrOverlayData> {
|
|||||||
m_nQueueFamilyIndex: graphics.queue.queue_family_index(),
|
m_nQueueFamilyIndex: graphics.queue.queue_family_index(),
|
||||||
};
|
};
|
||||||
|
|
||||||
graphics
|
log::info!("Usages: {:?}", image.usage());
|
||||||
.transition_layout(
|
|
||||||
image.clone(),
|
|
||||||
ImageLayout::ColorAttachmentOptimal,
|
|
||||||
ImageLayout::TransferSrcOptimal,
|
|
||||||
)
|
|
||||||
.wait(None)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
log::info!("nImage: {}, nFormat: {:?}, nWidth: {}, nHeight: {}, nSampleCount: {}, nQueueFamilyIndex: {}", texture.m_nImage, format, texture.m_nWidth, texture.m_nHeight, texture.m_nSampleCount, texture.m_nQueueFamilyIndex);
|
log::info!("nImage: {}, nFormat: {:?}, nWidth: {}, nHeight: {}, nSampleCount: {}, nQueueFamilyIndex: {}", texture.m_nImage, format, texture.m_nWidth, texture.m_nHeight, texture.m_nSampleCount, texture.m_nQueueFamilyIndex);
|
||||||
if let Err(e) = overlay.set_image_vulkan(handle, &mut texture) {
|
if let Err(e) = overlay.set_image_vulkan(handle, &mut texture) {
|
||||||
panic!("Failed to set overlay texture: {}", e);
|
panic!("Failed to set overlay texture: {}", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
graphics
|
|
||||||
.transition_layout(
|
|
||||||
image,
|
|
||||||
ImageLayout::TransferSrcOptimal,
|
|
||||||
ImageLayout::ColorAttachmentOptimal,
|
|
||||||
)
|
|
||||||
.wait(None)
|
|
||||||
.unwrap();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -134,23 +134,27 @@ impl WlxGraphics {
|
|||||||
.build_vk_surface(&event_loop, instance.clone())
|
.build_vk_surface(&event_loop, instance.clone())
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let (physical_device, queue_family_index) = instance
|
let (physical_device, my_extensions, queue_family_index) = instance
|
||||||
.enumerate_physical_devices()
|
.enumerate_physical_devices()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.filter(|p| {
|
.filter(|p| {
|
||||||
p.api_version() >= Version::V1_3 || p.supported_extensions().khr_dynamic_rendering
|
p.api_version() >= Version::V1_3 || p.supported_extensions().khr_dynamic_rendering
|
||||||
})
|
})
|
||||||
.filter(|p| {
|
.filter_map(|p| {
|
||||||
let runtime_extensions = vk_device_extensions_fn(p);
|
let runtime_extensions = vk_device_extensions_fn(&p);
|
||||||
debug!(
|
debug!(
|
||||||
"Device exts for {}: {:?}",
|
"Device exts for {}: {:?}",
|
||||||
p.properties().device_name,
|
p.properties().device_name,
|
||||||
&runtime_extensions
|
&runtime_extensions
|
||||||
);
|
);
|
||||||
let my_extensions = runtime_extensions.union(&device_extensions);
|
let my_extensions = runtime_extensions.union(&device_extensions);
|
||||||
p.supported_extensions().contains(&my_extensions)
|
if p.supported_extensions().contains(&my_extensions) {
|
||||||
|
Some((p, my_extensions))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.filter_map(|p| {
|
.filter_map(|(p, my_extensions)| {
|
||||||
p.queue_family_properties()
|
p.queue_family_properties()
|
||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
@@ -158,9 +162,9 @@ impl WlxGraphics {
|
|||||||
q.queue_flags.intersects(QueueFlags::GRAPHICS)
|
q.queue_flags.intersects(QueueFlags::GRAPHICS)
|
||||||
&& p.surface_support(i as u32, &surface).unwrap_or(false)
|
&& p.surface_support(i as u32, &surface).unwrap_or(false)
|
||||||
})
|
})
|
||||||
.map(|i| (p, i as u32))
|
.map(|i| (p, my_extensions, i as u32))
|
||||||
})
|
})
|
||||||
.min_by_key(|(p, _)| match p.properties().device_type {
|
.min_by_key(|(p, _, _)| match p.properties().device_type {
|
||||||
PhysicalDeviceType::DiscreteGpu => 0,
|
PhysicalDeviceType::DiscreteGpu => 0,
|
||||||
PhysicalDeviceType::IntegratedGpu => 1,
|
PhysicalDeviceType::IntegratedGpu => 1,
|
||||||
PhysicalDeviceType::VirtualGpu => 2,
|
PhysicalDeviceType::VirtualGpu => 2,
|
||||||
@@ -182,7 +186,7 @@ impl WlxGraphics {
|
|||||||
let (device, mut queues) = Device::new(
|
let (device, mut queues) = Device::new(
|
||||||
physical_device,
|
physical_device,
|
||||||
DeviceCreateInfo {
|
DeviceCreateInfo {
|
||||||
enabled_extensions: device_extensions,
|
enabled_extensions: my_extensions,
|
||||||
enabled_features: Features {
|
enabled_features: Features {
|
||||||
dynamic_rendering: true,
|
dynamic_rendering: true,
|
||||||
..Features::empty()
|
..Features::empty()
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ use glam::{Vec2, Vec3};
|
|||||||
use vulkano::{
|
use vulkano::{
|
||||||
command_buffer::{CommandBufferUsage, PrimaryAutoCommandBuffer},
|
command_buffer::{CommandBufferUsage, PrimaryAutoCommandBuffer},
|
||||||
format::Format,
|
format::Format,
|
||||||
image::{view::ImageView, AttachmentImage, ImageLayout, ImageViewAbstract},
|
image::{view::ImageView, AttachmentImage, ImageAccess, ImageLayout, ImageViewAbstract},
|
||||||
sampler::Filter,
|
sampler::Filter,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -209,6 +209,8 @@ pub struct Canvas<D, S> {
|
|||||||
|
|
||||||
pass_fg: WlxPass,
|
pass_fg: WlxPass,
|
||||||
pass_bg: WlxPass,
|
pass_bg: WlxPass,
|
||||||
|
|
||||||
|
first_render: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<D, S> Canvas<D, S> {
|
impl<D, S> Canvas<D, S> {
|
||||||
@@ -286,6 +288,7 @@ impl<D, S> Canvas<D, S> {
|
|||||||
view_final,
|
view_final,
|
||||||
pass_fg,
|
pass_fg,
|
||||||
pass_bg,
|
pass_bg,
|
||||||
|
first_render: true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -400,6 +403,22 @@ impl<D, S> OverlayRenderer for Canvas<D, S> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let image = self.view_final.image().inner().image.clone();
|
||||||
|
|
||||||
|
if self.first_render {
|
||||||
|
self.first_render = false;
|
||||||
|
} else {
|
||||||
|
self.canvas
|
||||||
|
.graphics
|
||||||
|
.transition_layout(
|
||||||
|
image.clone(),
|
||||||
|
ImageLayout::TransferSrcOptimal,
|
||||||
|
ImageLayout::ColorAttachmentOptimal,
|
||||||
|
)
|
||||||
|
.wait(None)
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
let mut cmd_buffer = self
|
let mut cmd_buffer = self
|
||||||
.canvas
|
.canvas
|
||||||
.graphics
|
.graphics
|
||||||
@@ -431,8 +450,18 @@ impl<D, S> OverlayRenderer for Canvas<D, S> {
|
|||||||
|
|
||||||
// mostly static text
|
// mostly static text
|
||||||
cmd_buffer.run_ref(&self.pass_fg);
|
cmd_buffer.run_ref(&self.pass_fg);
|
||||||
|
{
|
||||||
let _ = cmd_buffer.end_render_and_execute();
|
let _ = cmd_buffer.end_render_and_execute();
|
||||||
|
}
|
||||||
|
self.canvas
|
||||||
|
.graphics
|
||||||
|
.transition_layout(
|
||||||
|
image,
|
||||||
|
ImageLayout::ColorAttachmentOptimal,
|
||||||
|
ImageLayout::TransferSrcOptimal,
|
||||||
|
)
|
||||||
|
.wait(None)
|
||||||
|
.unwrap();
|
||||||
}
|
}
|
||||||
fn view(&mut self) -> Option<Arc<dyn ImageViewAbstract>> {
|
fn view(&mut self) -> Option<Arc<dyn ImageViewAbstract>> {
|
||||||
Some(self.view_final.clone())
|
Some(self.view_final.clone())
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ use std::{
|
|||||||
use vulkano::{
|
use vulkano::{
|
||||||
command_buffer::CommandBufferUsage,
|
command_buffer::CommandBufferUsage,
|
||||||
format::Format,
|
format::Format,
|
||||||
image::{view::ImageView, ImageAccess, ImageViewAbstract, ImmutableImage},
|
image::{view::ImageView, ImageAccess, ImageLayout, ImageViewAbstract, ImmutableImage},
|
||||||
Handle, VulkanObject,
|
Handle, VulkanObject,
|
||||||
};
|
};
|
||||||
use wlx_capture::{
|
use wlx_capture::{
|
||||||
@@ -144,13 +144,8 @@ impl ScreenRenderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl OverlayRenderer for ScreenRenderer {
|
impl OverlayRenderer for ScreenRenderer {
|
||||||
fn init(&mut self, app: &mut AppState) {
|
fn init(&mut self, _app: &mut AppState) {
|
||||||
self.receiver = Some(self.capture.init());
|
self.receiver = Some(self.capture.init());
|
||||||
let mut cmd = app
|
|
||||||
.graphics
|
|
||||||
.create_command_buffer(CommandBufferUsage::OneTimeSubmit);
|
|
||||||
let default_image = cmd.texture2d(1, 1, Format::R8G8B8A8_UNORM, vec![255, 0, 255, 255]);
|
|
||||||
let _ = cmd.end_and_execute();
|
|
||||||
}
|
}
|
||||||
fn render(&mut self, app: &mut AppState) {
|
fn render(&mut self, app: &mut AppState) {
|
||||||
let Some(receiver) = self.receiver.as_mut() else {
|
let Some(receiver) = self.receiver.as_mut() else {
|
||||||
@@ -169,6 +164,14 @@ impl OverlayRenderer for ScreenRenderer {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
app.graphics
|
||||||
|
.transition_layout(
|
||||||
|
new.inner().image.clone(),
|
||||||
|
ImageLayout::Undefined,
|
||||||
|
ImageLayout::TransferSrcOptimal,
|
||||||
|
)
|
||||||
|
.wait(None)
|
||||||
|
.unwrap();
|
||||||
self.view = Some(ImageView::new_default(new).unwrap());
|
self.view = Some(ImageView::new_default(new).unwrap());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user