Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New architecture for vk-video initialization. #857

Merged
merged 1 commit into from
Nov 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
924 changes: 909 additions & 15 deletions Cargo.lock

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion compositor_pipeline/src/pipeline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ pub struct PipelineCtx {
pub download_dir: Arc<PathBuf>,
pub event_emitter: Arc<EventEmitter>,
#[cfg(feature = "vk-video")]
pub vulkan_ctx: Option<Arc<vk_video::VulkanCtx>>,
pub vulkan_ctx: Option<graphics_context::VulkanCtx>,
}

impl std::fmt::Debug for PipelineCtx {
Expand All @@ -156,6 +156,7 @@ impl Pipeline {
opts.force_gpu,
opts.wgpu_features,
Default::default(),
None,
)?),
#[cfg(not(feature = "vk-video"))]
None => None,
Expand Down
10 changes: 5 additions & 5 deletions compositor_pipeline/src/pipeline/decoder/video/vulkan_video.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use std::{sync::Arc, time::Duration};
use compositor_render::{Frame, FrameData, InputId, Resolution};
use crossbeam_channel::{Receiver, Sender};
use tracing::{debug, error, span, trace, warn, Level};
use vk_video::{VulkanCtx, WgpuTexturesDeocder};
use vk_video::VulkanDevice;

use crate::{
error::InputInitError,
Expand All @@ -17,7 +17,7 @@ pub fn start_vulkan_video_decoder_thread(
frame_sender: Sender<PipelineEvent<Frame>>,
input_id: InputId,
) -> Result<(), InputInitError> {
let Some(vulkan_ctx) = pipeline_ctx.vulkan_ctx.as_ref().map(|ctx| ctx.clone()) else {
let Some(vulkan_ctx) = pipeline_ctx.vulkan_ctx.clone() else {
return Err(InputInitError::VulkanContextRequiredForVulkanDecoder);
};

Expand All @@ -33,7 +33,7 @@ pub fn start_vulkan_video_decoder_thread(
)
.entered();
run_decoder_thread(
vulkan_ctx,
vulkan_ctx.device,
init_result_sender,
chunks_receiver,
frame_sender,
Expand All @@ -47,12 +47,12 @@ pub fn start_vulkan_video_decoder_thread(
}

fn run_decoder_thread(
vulkan_ctx: Arc<VulkanCtx>,
vulkan_device: Arc<VulkanDevice>,
init_result_sender: Sender<Result<(), InputInitError>>,
chunks_receiver: Receiver<PipelineEvent<EncodedChunk>>,
frame_sender: Sender<PipelineEvent<Frame>>,
) {
let mut decoder = match WgpuTexturesDeocder::new(vulkan_ctx) {
let mut decoder = match vulkan_device.create_wgpu_textures_decoder() {
Ok(decoder) => {
init_result_sender.send(Ok(())).unwrap();
decoder
Expand Down
55 changes: 45 additions & 10 deletions compositor_pipeline/src/pipeline/graphics_context.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,23 @@
use crate::error::InitPipelineError;
use compositor_render::{create_wgpu_ctx, error::InitRendererEngineError};
use compositor_render::{create_wgpu_ctx, error::InitRendererEngineError, WgpuComponents};
use std::sync::Arc;

#[cfg(feature = "vk-video")]
#[derive(Debug, Clone)]
pub struct VulkanCtx {
pub device: Arc<vk_video::VulkanDevice>,
pub instance: Arc<vk_video::VulkanInstance>,
}

#[derive(Debug)]
pub struct GraphicsContext {
pub device: Arc<wgpu::Device>,
pub queue: Arc<wgpu::Queue>,
pub adapter: Arc<wgpu::Adapter>,
pub instance: Arc<wgpu::Instance>,

jerzywilczek marked this conversation as resolved.
Show resolved Hide resolved
#[cfg(feature = "vk-video")]
pub vulkan_ctx: Option<Arc<vk_video::VulkanCtx>>,
pub vulkan_ctx: Option<VulkanCtx>,
}

impl GraphicsContext {
Expand All @@ -17,6 +26,7 @@ impl GraphicsContext {
force_gpu: bool,
features: wgpu::Features,
limits: wgpu::Limits,
mut compatible_surface: Option<&mut wgpu::Surface<'_>>,
) -> Result<Self, InitPipelineError> {
use compositor_render::{required_wgpu_features, set_required_wgpu_limits};
use tracing::warn;
Expand All @@ -26,22 +36,36 @@ impl GraphicsContext {

let limits = set_required_wgpu_limits(limits);

match vk_video::VulkanCtx::new(vulkan_features, limits.clone()) {
Ok(ctx) => Ok(GraphicsContext {
device: ctx.wgpu_ctx.device.clone(),
queue: ctx.wgpu_ctx.queue.clone(),
vulkan_ctx: Some(ctx.into()),
match vk_video::VulkanInstance::new().and_then(|instance| {
let device =
instance.create_device(vulkan_features, limits.clone(), &mut compatible_surface)?;

Ok((instance, device))
}) {
Ok((instance, device)) => Ok(GraphicsContext {
device: device.wgpu_device.clone(),
queue: device.wgpu_queue.clone(),
adapter: device.wgpu_adapter.clone(),
instance: instance.wgpu_instance.clone(),
vulkan_ctx: Some(VulkanCtx { instance, device }),
}),

Err(err) => {
warn!("Cannot initialize vulkan video decoding context. Reason: {err}. Initializing without vulkan video support.");

let (device, queue) = create_wgpu_ctx(force_gpu, features, limits)
let WgpuComponents {
instance,
adapter,
device,
queue,
} = create_wgpu_ctx(force_gpu, features, limits, compatible_surface.as_deref())
.map_err(InitRendererEngineError::FailedToInitWgpuCtx)?;

Ok(GraphicsContext {
device,
queue,
adapter,
instance,
vulkan_ctx: None,
})
}
Expand All @@ -53,10 +77,21 @@ impl GraphicsContext {
force_gpu: bool,
features: wgpu::Features,
limits: wgpu::Limits,
compatible_surface: Option<&mut wgpu::Surface<'_>>,
) -> Result<Self, InitPipelineError> {
let (device, queue) = create_wgpu_ctx(force_gpu, features, limits)
let WgpuComponents {
instance,
adapter,
device,
queue,
} = create_wgpu_ctx(force_gpu, features, limits, compatible_surface.as_deref())
.map_err(InitRendererEngineError::FailedToInitWgpuCtx)?;

Ok(GraphicsContext { device, queue })
Ok(GraphicsContext {
device,
queue,
adapter,
instance,
})
}
}
2 changes: 1 addition & 1 deletion compositor_render/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ pub use state::RendererOptions;
pub use state::RendererSpec;

pub use wgpu::WgpuFeatures;
pub use wgpu::{create_wgpu_ctx, required_wgpu_features, set_required_wgpu_limits};
pub use wgpu::{create_wgpu_ctx, required_wgpu_features, set_required_wgpu_limits, WgpuComponents};

pub mod image {
pub use crate::transformations::image_renderer::{ImageSource, ImageSpec, ImageType};
Expand Down
2 changes: 1 addition & 1 deletion compositor_render/src/wgpu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ pub(crate) mod texture;
pub(crate) mod utils;

pub(crate) use ctx::WgpuCtx;
pub use ctx::{create_wgpu_ctx, required_wgpu_features, set_required_wgpu_limits};
pub use ctx::{create_wgpu_ctx, required_wgpu_features, set_required_wgpu_limits, WgpuComponents};
pub use wgpu::Features as WgpuFeatures;

#[must_use]
Expand Down
23 changes: 19 additions & 4 deletions compositor_render/src/wgpu/ctx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ impl WgpuCtx {
Self::new_from_device_queue(device, queue)?
}
None => {
let (device, queue) = create_wgpu_ctx(force_gpu, features, Default::default())?;
let WgpuComponents { device, queue, .. } =
create_wgpu_ctx(force_gpu, features, Default::default(), None)?;
Self::new_from_device_queue(device, queue)?
}
};
Expand Down Expand Up @@ -101,11 +102,20 @@ pub fn set_required_wgpu_limits(limits: wgpu::Limits) -> wgpu::Limits {
}
}

#[derive(Clone)]
pub struct WgpuComponents {
pub device: Arc<wgpu::Device>,
pub queue: Arc<wgpu::Queue>,
pub adapter: Arc<wgpu::Adapter>,
pub instance: Arc<wgpu::Instance>,
}

pub fn create_wgpu_ctx(
force_gpu: bool,
features: wgpu::Features,
limits: wgpu::Limits,
) -> Result<(Arc<wgpu::Device>, Arc<wgpu::Queue>), CreateWgpuCtxError> {
compatible_surface: Option<&wgpu::Surface<'_>>,
) -> Result<WgpuComponents, CreateWgpuCtxError> {
let instance = wgpu::Instance::new(wgpu::InstanceDescriptor {
backends: wgpu::Backends::all(),
..Default::default()
Expand All @@ -117,7 +127,7 @@ pub fn create_wgpu_ctx(
let adapter = pollster::block_on(instance.request_adapter(&wgpu::RequestAdapterOptionsBase {
power_preference: wgpu::PowerPreference::HighPerformance,
force_fallback_adapter: false,
compatible_surface: None,
compatible_surface,
}))
.ok_or(CreateWgpuCtxError::NoAdapter)?;

Expand Down Expand Up @@ -148,7 +158,12 @@ pub fn create_wgpu_ctx(
},
None,
))?;
Ok((device.into(), queue.into()))
Ok(WgpuComponents {
instance: instance.into(),
adapter: adapter.into(),
device: device.into(),
queue: queue.into(),
})
}

fn uniform_bind_group_layout(device: &wgpu::Device) -> wgpu::BindGroupLayout {
Expand Down
27 changes: 9 additions & 18 deletions integration_tests/examples/manual_graphics_initialization.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,27 +9,18 @@ fn main() {
};
use live_compositor::config::read_config;

let graphics_context =
GraphicsContext::new(false, wgpu::Features::default(), wgpu::Limits::default()).unwrap();
let graphics_context = GraphicsContext::new(
false,
wgpu::Features::default(),
wgpu::Limits::default(),
None,
)
.unwrap();

let _device = graphics_context.device.clone();
let _queue = graphics_context.queue.clone();

let _adapter = graphics_context
.vulkan_ctx
.as_ref()
.unwrap()
.wgpu_ctx
.adapter
.clone();

let _instance = graphics_context
.vulkan_ctx
.as_ref()
.unwrap()
.wgpu_ctx
.instance
.clone();
let _adapter = graphics_context.adapter.clone();
let _instance = graphics_context.instance.clone();

let config = read_config();

Expand Down
2 changes: 1 addition & 1 deletion integration_tests/examples/raw_channel_input.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ fn main() {
ffmpeg_next::format::network::init();
let config = read_config();
logger::init_logger(config.logger);
let ctx = GraphicsContext::new(false, Default::default(), Default::default()).unwrap();
let ctx = GraphicsContext::new(false, Default::default(), Default::default(), None).unwrap();
let (wgpu_device, wgpu_queue) = (ctx.device.clone(), ctx.queue.clone());
// no chromium support, so we can ignore _event_loop
let (pipeline, _event_loop) = Pipeline::new(Options {
Expand Down
2 changes: 1 addition & 1 deletion integration_tests/examples/raw_channel_output.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ fn main() {
logger::init_logger(read_config().logger);
let mut config = read_config();
config.queue_options.ahead_of_time_processing = true;
let ctx = GraphicsContext::new(false, Default::default(), Default::default()).unwrap();
let ctx = GraphicsContext::new(false, Default::default(), Default::default(), None).unwrap();
let (wgpu_device, wgpu_queue) = (ctx.device.clone(), ctx.queue.clone());
// no chromium support, so we can ignore _event_loop
let (pipeline, _event_loop) = Pipeline::new(Options {
Expand Down
4 changes: 2 additions & 2 deletions integration_tests/examples/vulkan.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ fn client_code() -> Result<()> {
const INPUT_PORT: u16 = 8006;
const OUTPUT_PORT: u16 = 8004;

const VIDEOS: u16 = 1;
const VIDEOS: u16 = 6;
start_ffmpeg_receive(Some(OUTPUT_PORT), None)?;

let config = read_config();
Expand Down Expand Up @@ -176,7 +176,7 @@ fn client_code() -> Result<()> {
Pipeline::start(&pipeline);

for i in 0..VIDEOS {
start_ffmpeg_send(IP, Some(INPUT_PORT + 2 * i), None, TestSample::Sample)?;
start_ffmpeg_send(IP, Some(INPUT_PORT + 2 * i), None, TestSample::BigBuckBunny)?;
}

let event_loop_fallback = || {
Expand Down
23 changes: 11 additions & 12 deletions src/snapshot_tests/utils.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,10 @@
use core::panic;
use std::{
io::Write,
sync::{Arc, OnceLock},
time::Duration,
};
use std::{io::Write, sync::OnceLock, time::Duration};

use bytes::BufMut;
use compositor_render::{
create_wgpu_ctx, web_renderer, Frame, FrameData, Framerate, Renderer, RendererOptions,
WgpuFeatures, YuvPlanes,
WgpuComponents, WgpuFeatures, YuvPlanes,
};
use crossbeam_channel::bounded;
use tracing::error;
Expand Down Expand Up @@ -57,13 +53,16 @@ pub(super) fn yuv_frame_to_rgba(frame: &Frame, planes: &YuvPlanes) -> Vec<u8> {
rgba_data
}

fn get_wgpu_ctx() -> (Arc<wgpu::Device>, Arc<wgpu::Queue>) {
static CTX: OnceLock<(Arc<wgpu::Device>, Arc<wgpu::Queue>)> = OnceLock::new();
CTX.get_or_init(|| create_wgpu_ctx(false, Default::default(), Default::default()).unwrap())
.clone()
fn get_wgpu_ctx() -> WgpuComponents {
static CTX: OnceLock<WgpuComponents> = OnceLock::new();
CTX.get_or_init(|| {
create_wgpu_ctx(false, Default::default(), Default::default(), None).unwrap()
})
.clone()
}

pub(super) fn create_renderer() -> Renderer {
let wgpu_ctx = get_wgpu_ctx();
let (renderer, _event_loop) = Renderer::new(RendererOptions {
web_renderer: web_renderer::WebRendererInitOptions {
enable: false,
Expand All @@ -73,15 +72,15 @@ pub(super) fn create_renderer() -> Renderer {
framerate: Framerate { num: 30, den: 1 },
stream_fallback_timeout: Duration::from_secs(3),
wgpu_features: WgpuFeatures::default(),
wgpu_ctx: Some(get_wgpu_ctx()),
wgpu_ctx: Some((wgpu_ctx.device.clone(), wgpu_ctx.queue.clone())),
load_system_fonts: false,
})
.unwrap();
renderer
}

fn read_rgba_texture(texture: &wgpu::Texture) -> bytes::Bytes {
let (device, queue) = get_wgpu_ctx();
let WgpuComponents { device, queue, .. } = get_wgpu_ctx();
let buffer = new_download_buffer(&device, texture);

let mut encoder = device.create_command_encoder(&Default::default());
Expand Down
3 changes: 3 additions & 0 deletions vk-video/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ repository = "https://github.com/software-mansion/live-compositor"

[dependencies]
ash = "0.38.0"
bytemuck = { version = "1.19.0", features = ["derive"] }
bytes = "1"
derivative = "2.2.0"
h264-reader = { git = "https://github.com/membraneframework-labs/h264-reader.git", branch = "live-compositor" }
Expand All @@ -21,6 +22,8 @@ wgpu = "23.0.0"

[dev-dependencies]
tracing-subscriber = "0.3.18"
winit = "0.29"
clap = { version = "4.5.20", features = ["derive"] }

[build-dependencies]
cfg_aliases = "0.2.1"
Loading
Loading