diff options
author | David Riley <davidriley@chromium.org> | 2018-05-17 17:14:42 -0700 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2018-07-30 23:08:04 -0700 |
commit | f89e0b50e20c39cc2e9b22f83de1e8fee6b8803f (patch) | |
tree | dab148d1d924098bc33dab14a2e3cf4f6252a73a /devices/src/virtio/gpu/mod.rs | |
parent | ba7c6035f8fb4b939b9c86f58c0f3009b04ebb68 (diff) | |
download | crosvm-f89e0b50e20c39cc2e9b22f83de1e8fee6b8803f.tar crosvm-f89e0b50e20c39cc2e9b22f83de1e8fee6b8803f.tar.gz crosvm-f89e0b50e20c39cc2e9b22f83de1e8fee6b8803f.tar.bz2 crosvm-f89e0b50e20c39cc2e9b22f83de1e8fee6b8803f.tar.lz crosvm-f89e0b50e20c39cc2e9b22f83de1e8fee6b8803f.tar.xz crosvm-f89e0b50e20c39cc2e9b22f83de1e8fee6b8803f.tar.zst crosvm-f89e0b50e20c39cc2e9b22f83de1e8fee6b8803f.zip |
gpu: add support for fences
BUG=None TEST=build with --features=gpu; null_platform_test Change-Id: Ib863c8ef3e85aa0f345c1f20be414979808b6a17 Reviewed-on: https://chromium-review.googlesource.com/1073959 Commit-Ready: David Riley <davidriley@chromium.org> Tested-by: David Riley <davidriley@chromium.org> Reviewed-by: Zach Reizner <zachr@chromium.org>
Diffstat (limited to 'devices/src/virtio/gpu/mod.rs')
-rw-r--r-- | devices/src/virtio/gpu/mod.rs | 65 |
1 files changed, 62 insertions, 3 deletions
diff --git a/devices/src/virtio/gpu/mod.rs b/devices/src/virtio/gpu/mod.rs index 2b223fc..24b6fe5 100644 --- a/devices/src/virtio/gpu/mod.rs +++ b/devices/src/virtio/gpu/mod.rs @@ -9,14 +9,16 @@ extern crate gpu_renderer; mod protocol; mod backend; -use std::rc::Rc; use std::cell::RefCell; use std::collections::VecDeque; +use std::i64; use std::mem::size_of; use std::os::unix::io::RawFd; +use std::rc::Rc; use std::sync::Arc; use std::sync::atomic::{AtomicUsize, Ordering}; use std::thread::spawn; +use std::time::Duration; use data_model::*; @@ -35,6 +37,7 @@ use self::backend::Backend; // First queue is for virtio gpu commands. Second queue is for cursor commands, which we expect // there to be fewer of. const QUEUE_SIZES: &'static [u16] = &[256, 16]; +const FENCE_POLL_MS: u64 = 1; struct QueueDescriptor { index: u16, @@ -49,11 +52,18 @@ struct ReturnDescriptor { len: u32, } +struct FenceDescriptor { + fence_id: u32, + len: u32, + desc: QueueDescriptor, +} + struct Frontend { ctrl_descriptors: VecDeque<QueueDescriptor>, cursor_descriptors: VecDeque<QueueDescriptor>, return_ctrl_descriptors: VecDeque<ReturnDescriptor>, return_cursor_descriptors: VecDeque<ReturnDescriptor>, + fence_descriptors: Vec<FenceDescriptor>, backend: Backend, } @@ -64,6 +74,7 @@ impl Frontend { cursor_descriptors: Default::default(), return_ctrl_descriptors: Default::default(), return_cursor_descriptors: Default::default(), + fence_descriptors: Default::default(), backend, } } @@ -373,17 +384,40 @@ impl Frontend { let mut flags = 0; if let Some(cmd) = gpu_cmd { let ctrl_hdr = cmd.ctrl_hdr(); - // TODO: add proper fence support if ctrl_hdr.flags.to_native() & VIRTIO_GPU_FLAG_FENCE != 0 { fence_id = ctrl_hdr.fence_id.to_native(); ctx_id = ctrl_hdr.ctx_id.to_native(); flags = VIRTIO_GPU_FLAG_FENCE; + + let fence_resp = self.backend + .create_fence(ctx_id, fence_id as u32); + if fence_resp.is_err() { + warn!("create_fence {} -> {:?}", + fence_id, fence_resp); + resp = fence_resp; + } } } + + + // Prepare the response now, even if it is going to wait until + // fence is complete. match resp.encode(flags, fence_id, ctx_id, ret_desc_mem) { Ok(l) => len = l, Err(e) => debug!("ctrl queue response encode error: {:?}", e), } + + if flags & VIRTIO_GPU_FLAG_FENCE != 0 { + self.fence_descriptors.push(FenceDescriptor { + fence_id: fence_id as u32, + len, + desc, + }); + + return None + } + + // No fence, respond now. } } Some(ReturnDescriptor { @@ -411,6 +445,22 @@ impl Frontend { .and_then(|desc| self.process_descriptor(mem, desc)) }) } + + fn fence_poll(&mut self) { + let fence_id = self.backend.fence_poll(); + let return_descs = &mut self.return_ctrl_descriptors; + self.fence_descriptors.retain(|f_desc| { + if f_desc.fence_id > fence_id { + true + } else { + return_descs.push_back(ReturnDescriptor { + index: f_desc.desc.index, + len: f_desc.len + }); + false + } + }) + } } struct Worker { @@ -462,7 +512,14 @@ impl Worker { }; 'poll: loop { - let events = match poll_ctx.wait() { + // If there are outstanding fences, wake up early to poll them. + let duration = if self.state.fence_descriptors.len() != 0 { + Duration::from_millis(FENCE_POLL_MS) + } else { + Duration::new(i64::MAX as u64, 0) + }; + + let events = match poll_ctx.wait_timeout(duration) { Ok(v) => v, Err(e) => { error!("failed polling for events: {:?}", e); @@ -505,6 +562,8 @@ impl Worker { } } + self.state.fence_poll(); + loop { match self.state.process_ctrl(&self.mem) { Some(ReturnDescriptor { index, len }) => { |