rusticl/event: flush queues from dependencies

We have to flush all event dependencies inside clWaitForEvents and
clFinish implicitly otherwise applications might wait forever.

Closes: https://gitlab.freedesktop.org/mesa/mesa/-/issues/9052
Fixes: ebfffa1dae ("rusticl/event: wrong but non crashing impl of clWaitForEvents")
Cc: mesa-stable
Signed-off-by: Karol Herbst <git@karolherbst.de>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/23110>
This commit is contained in:
Karol Herbst
2023-05-20 22:29:10 +02:00
committed by Marge Bot
parent 86dd5dd853
commit 8616c0a52c
4 changed files with 56 additions and 6 deletions

View File

@@ -74,13 +74,14 @@ pub fn wait_for_events(num_events: cl_uint, event_list: *const cl_event) -> CLRe
return Err(CL_INVALID_CONTEXT);
}
// TODO better impl
// find all queues we have to flush
for q in Event::deep_unflushed_queues(&evs) {
q.flush(false)?;
}
// now wait on all events and check if we got any errors
let mut err = false;
for e in evs {
if let Some(q) = &e.queue {
q.flush(false)?;
}
err |= e.wait() < 0;
}

View File

@@ -195,7 +195,13 @@ pub fn flush_queue(command_queue: cl_command_queue) -> CLResult<()> {
pub fn finish_queue(command_queue: cl_command_queue) -> CLResult<()> {
// CL_INVALID_COMMAND_QUEUE if command_queue is not a valid host command-queue.
command_queue.get_ref()?.flush(true)
let q = command_queue.get_ref()?;
for q in q.dependencies_for_pending_events() {
q.flush(false)?;
}
q.flush(true)
}
pub fn release_command_queue(command_queue: cl_command_queue) -> CLResult<()> {

View File

@@ -9,6 +9,7 @@ use mesa_rust::pipe::fence::*;
use mesa_rust_util::static_assert;
use rusticl_opencl_gen::*;
use std::collections::HashSet;
use std::os::raw::c_void;
use std::slice;
use std::sync::Arc;
@@ -185,6 +186,39 @@ impl Event {
status
}
}
fn deep_unflushed_deps_impl<'a>(&'a self, result: &mut HashSet<&'a Event>) {
if self.status() <= CL_SUBMITTED as i32 {
return;
}
// only scan dependencies if it's a new one
if result.insert(self) {
for e in &self.deps {
e.deep_unflushed_deps_impl(result);
}
}
}
/// does a deep search and returns a list of all dependencies including `events` which haven't
/// been flushed out yet
pub fn deep_unflushed_deps(events: &[Arc<Event>]) -> HashSet<&Event> {
let mut result = HashSet::new();
for e in events {
e.deep_unflushed_deps_impl(&mut result);
}
result
}
/// does a deep search and returns a list of all queues which haven't been flushed yet
pub fn deep_unflushed_queues(events: &[Arc<Event>]) -> HashSet<Arc<Queue>> {
Event::deep_unflushed_deps(events)
.iter()
.filter_map(|e| e.queue.clone())
.collect()
}
}
// TODO worker thread per device

View File

@@ -7,6 +7,7 @@ use crate::impl_cl_type_trait;
use mesa_rust_util::properties::*;
use rusticl_opencl_gen::*;
use std::collections::HashSet;
use std::sync::mpsc;
use std::sync::Arc;
use std::sync::Mutex;
@@ -93,6 +94,14 @@ impl Queue {
}
Ok(())
}
pub fn dependencies_for_pending_events(&self) -> HashSet<Arc<Queue>> {
let p = self.pending.lock().unwrap();
let mut queues = Event::deep_unflushed_queues(&p);
queues.remove(self);
queues
}
}
impl Drop for Queue {