devices: gpu: add render server support
When "--gpu-render-server path=<path>" is specified, start the render
server shipped with virglrenderer and initialize virglrenderer with
VIRGLRENDERER_MULTI_PROCESS flag.
The flag makes virgl_renderer_context_create_with_flags create proxy
contexts instead of venus contexts. Each proxy context requests the
render server to fork a subprocess and executes GPU commands in the
subprocess.
BUG=b:177267762
TEST=run vk and gl apps on volteer
Change-Id: If5e2dc3353572cadb60b0c25a3e0ad14f633db91
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/3283508
Reviewed-by: Chirantan Ekbote <chirantan@chromium.org>
Reviewed-by: Daniel Verkamp <dverkamp@chromium.org>
Tested-by: kokoro <noreply+kokoro@google.com>
Commit-Queue: Chia-I Wu <olv@google.com>
diff --git a/src/main.rs b/src/main.rs
index 557847a..2cb3361 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -39,7 +39,8 @@
#[cfg(feature = "gpu")]
use devices::virtio::{
gpu::{
- GpuDisplayParameters, GpuMode, GpuParameters, DEFAULT_DISPLAY_HEIGHT, DEFAULT_DISPLAY_WIDTH,
+ GpuDisplayParameters, GpuMode, GpuParameters, GpuRenderServerParameters,
+ DEFAULT_DISPLAY_HEIGHT, DEFAULT_DISPLAY_WIDTH,
},
vhost::user::device::run_gpu_device,
};
@@ -541,6 +542,52 @@
Ok(())
}
+#[cfg(all(feature = "gpu", feature = "virgl_renderer_next"))]
+fn parse_gpu_render_server_options(
+ s: Option<&str>,
+ gpu_params: &mut GpuParameters,
+) -> argument::Result<()> {
+ let mut path: Option<PathBuf> = None;
+
+ if let Some(s) = s {
+ let opts = s
+ .split(',')
+ .map(|frag| frag.split('='))
+ .map(|mut kv| (kv.next().unwrap_or(""), kv.next().unwrap_or("")));
+
+ for (k, v) in opts {
+ match k {
+ "path" => {
+ path =
+ Some(
+ PathBuf::from_str(v).map_err(|e| argument::Error::InvalidValue {
+ value: v.to_string(),
+ expected: e.to_string(),
+ })?,
+ )
+ }
+ "" => {}
+ _ => {
+ return Err(argument::Error::UnknownArgument(format!(
+ "gpu-render-server parameter {}",
+ k
+ )));
+ }
+ }
+ }
+ }
+
+ if let Some(p) = path {
+ gpu_params.render_server = Some(GpuRenderServerParameters { path: p });
+ Ok(())
+ } else {
+ Err(argument::Error::InvalidValue {
+ value: s.unwrap_or("").to_string(),
+ expected: String::from("gpu-render-server must include 'path'"),
+ })
+ }
+}
+
#[cfg(feature = "audio")]
fn parse_ac97_options(s: &str) -> argument::Result<Ac97Parameters> {
let mut ac97_params: Ac97Parameters = Default::default();
@@ -1802,17 +1849,18 @@
}
#[cfg(feature = "gpu")]
"gpu" => {
- if cfg.gpu_parameters.is_none() {
- cfg.gpu_parameters = Some(Default::default());
- }
- parse_gpu_options(value, cfg.gpu_parameters.as_mut().unwrap())?;
+ let gpu_parameters = cfg.gpu_parameters.get_or_insert_with(Default::default);
+ parse_gpu_options(value, gpu_parameters)?;
}
#[cfg(feature = "gpu")]
"gpu-display" => {
- if cfg.gpu_parameters.is_none() {
- cfg.gpu_parameters = Some(Default::default());
- }
- parse_gpu_display_options(value, cfg.gpu_parameters.as_mut().unwrap())?;
+ let gpu_parameters = cfg.gpu_parameters.get_or_insert_with(Default::default);
+ parse_gpu_display_options(value, gpu_parameters)?;
+ }
+ #[cfg(all(feature = "gpu", feature = "virgl_renderer_next"))]
+ "gpu-render-server" => {
+ let gpu_parameters = cfg.gpu_parameters.get_or_insert_with(Default::default);
+ parse_gpu_render_server_options(value, gpu_parameters)?;
}
"software-tpm" => {
cfg.software_tpm = true;
@@ -2351,6 +2399,12 @@
Possible key values:
width=INT - The width of the virtual display connected to the virtio-gpu.
height=INT - The height of the virtual display connected to the virtio-gpu."),
+ #[cfg(all(feature = "gpu", feature = "virgl_renderer_next"))]
+ Argument::flag_or_value("gpu-render-server",
+ "[path=PATH]",
+ "(EXPERIMENTAL) Comma separated key=value pairs for setting up a render server for the virtio-gpu device
+ Possible key values:
+ path=PATH - The path to the render server executable."),
#[cfg(feature = "tpm")]
Argument::flag("software-tpm", "enable a software emulated trusted platform module device"),
Argument::value("evdev", "PATH", "Path to an event device node. The device will be grabbed (unusable from the host) and made available to the guest with the same configuration it shows on the host"),