diff --git a/src/gallium/frontends/rusticl/core/event.rs b/src/gallium/frontends/rusticl/core/event.rs index daff5c4e950..6f45bb59140 100644 --- a/src/gallium/frontends/rusticl/core/event.rs +++ b/src/gallium/frontends/rusticl/core/event.rs @@ -4,7 +4,6 @@ use crate::core::context::*; use crate::core::queue::*; use crate::impl_cl_type_trait; -use mesa_rust::pipe::context::*; use mesa_rust::pipe::query::*; use mesa_rust_gen::*; use mesa_rust_util::static_assert; @@ -24,7 +23,7 @@ static_assert!(CL_RUNNING == 1); static_assert!(CL_SUBMITTED == 2); static_assert!(CL_QUEUED == 3); -pub type EventSig = Box, &PipeContext) -> CLResult<()>>; +pub type EventSig = Box, &QueueContext) -> CLResult<()>>; pub enum EventTimes { Queued = CL_PROFILING_COMMAND_QUEUED as isize, @@ -194,7 +193,7 @@ impl Event { // We always assume that work here simply submits stuff to the hardware even if it's just doing // sw emulation or nothing at all. // If anything requets waiting, we will update the status through fencing later. - pub fn call(&self, ctx: &PipeContext) { + pub fn call(&self, ctx: &QueueContext) { let mut lock = self.state(); let status = lock.status; let queue = self.queue.as_ref().unwrap(); diff --git a/src/gallium/frontends/rusticl/core/queue.rs b/src/gallium/frontends/rusticl/core/queue.rs index bd58247b7d9..c089aa4af8a 100644 --- a/src/gallium/frontends/rusticl/core/queue.rs +++ b/src/gallium/frontends/rusticl/core/queue.rs @@ -10,6 +10,7 @@ use mesa_rust_util::properties::*; use rusticl_opencl_gen::*; use std::mem; +use std::ops::Deref; use std::sync::mpsc; use std::sync::Arc; use std::sync::Mutex; @@ -17,6 +18,33 @@ use std::sync::Weak; use std::thread; use std::thread::JoinHandle; +/// State tracking wrapper for [PipeContext] +/// +/// Used for tracking bound GPU state to lower CPU overhead and centralize state tracking +pub struct QueueContext { + ctx: PipeContext, +} + +impl QueueContext { + fn new_for(device: &Device) -> CLResult { + Ok(Self { + ctx: device + .screen() + .create_context() + .ok_or(CL_OUT_OF_HOST_MEMORY)?, + }) + } +} + +// This should go once we moved all state tracking into QueueContext +impl Deref for QueueContext { + type Target = PipeContext; + + fn deref(&self) -> &Self::Target { + &self.ctx + } +} + struct QueueState { pending: Vec>, last: Weak, @@ -53,7 +81,7 @@ impl Queue { ) -> CLResult> { // we assume that memory allocation is the only possible failure. Any other failure reason // should be detected earlier (e.g.: checking for CAPs). - let pipe = device.screen().create_context().unwrap(); + let ctx = QueueContext::new_for(device)?; let (tx_q, rx_t) = mpsc::channel::>>(); Ok(Arc::new(Self { base: CLObjectBase::new(), @@ -81,7 +109,7 @@ impl Queue { // If we hit any deps from another queue, flush so we don't risk a dead // lock. if e.deps.iter().any(|ev| ev.queue != e.queue) { - flush_events(&mut flushed, &pipe); + flush_events(&mut flushed, &ctx); } // We have to wait on user events or events from other queues. @@ -98,25 +126,25 @@ impl Queue { continue; } - e.call(&pipe); + e.call(&ctx); if e.is_user() { // On each user event we flush our events as application might // wait on them before signaling user events. - flush_events(&mut flushed, &pipe); + flush_events(&mut flushed, &ctx); // Wait on user events as they are synchronization points in the // application's control. e.wait(); } else if Platform::dbg().sync_every_event { flushed.push(e); - flush_events(&mut flushed, &pipe); + flush_events(&mut flushed, &ctx); } else { flushed.push(e); } } - flush_events(&mut flushed, &pipe); + flush_events(&mut flushed, &ctx); }) .unwrap(), }))