From 20a3ec2d771d7f8942018b714c64925a870a2062 Mon Sep 17 00:00:00 2001 From: Karol Herbst Date: Wed, 4 Nov 2020 23:05:51 +0100 Subject: [PATCH] clover/queue: Flush automatically if applications do not flush themselves With the image_read_write OpenCL CTS we can get a stack overflow handling all the events as the application itself never flushes. We need to address this in two ways: 1. flush the queue once an abritary amoung of events piled up. 2. Drop event deps once they get a fence assigned. Signed-off-by: Karol Herbst Reviewed-by: Francisco Jerez Part-of: --- src/gallium/frontends/clover/core/event.cpp | 7 ++++++- src/gallium/frontends/clover/core/event.hpp | 2 +- src/gallium/frontends/clover/core/queue.cpp | 13 ++++++++++++- src/gallium/frontends/clover/core/queue.hpp | 2 ++ 4 files changed, 21 insertions(+), 3 deletions(-) diff --git a/src/gallium/frontends/clover/core/event.cpp b/src/gallium/frontends/clover/core/event.cpp index 3d313ce8969..823b243b1a5 100644 --- a/src/gallium/frontends/clover/core/event.cpp +++ b/src/gallium/frontends/clover/core/event.cpp @@ -118,7 +118,10 @@ event::wait_signalled() const { void event::wait() const { - for (event &ev : deps) + std::vector> evs; + std::swap(deps, evs); + + for (event &ev : evs) ev.wait(); wait_signalled(); @@ -203,8 +206,10 @@ hard_event::time_end() const { void hard_event::fence(pipe_fence_handle *fence) { + assert(fence); pipe_screen *screen = queue()->device().pipe; screen->fence_reference(screen, &_fence, fence); + deps.clear(); } event::action diff --git a/src/gallium/frontends/clover/core/event.hpp b/src/gallium/frontends/clover/core/event.hpp index 03c97bcf4da..5817893d0da 100644 --- a/src/gallium/frontends/clover/core/event.hpp +++ b/src/gallium/frontends/clover/core/event.hpp @@ -81,7 +81,7 @@ namespace clover { protected: void chain(event &ev); - std::vector> deps; + mutable std::vector> deps; private: std::vector> trigger_self(); diff --git a/src/gallium/frontends/clover/core/queue.cpp b/src/gallium/frontends/clover/core/queue.cpp index c91b97ad15e..c7d08a8c6d2 100644 --- a/src/gallium/frontends/clover/core/queue.cpp +++ b/src/gallium/frontends/clover/core/queue.cpp @@ -65,10 +65,15 @@ command_queue::~command_queue() { void command_queue::flush() { + std::lock_guard lock(queued_events_mutex); + flush_unlocked(); +} + +void +command_queue::flush_unlocked() { pipe_screen *screen = device().pipe; pipe_fence_handle *fence = NULL; - std::lock_guard lock(queued_events_mutex); if (!queued_events.empty()) { pipe->flush(pipe, &fence, 0); @@ -99,4 +104,10 @@ command_queue::sequence(hard_event &ev) { queued_events.back()().chain(ev); queued_events.push_back(ev); + + // Arbitrary threshold. + // The CTS tends to run a lot of subtests without flushing with the image + // tests, so flush regulary to prevent stack overflows. + if (queued_events.size() > 1000) + flush_unlocked(); } diff --git a/src/gallium/frontends/clover/core/queue.hpp b/src/gallium/frontends/clover/core/queue.hpp index bddb86c0e4c..27f2c9b7aeb 100644 --- a/src/gallium/frontends/clover/core/queue.hpp +++ b/src/gallium/frontends/clover/core/queue.hpp @@ -67,6 +67,8 @@ namespace clover { /// Serialize a hardware event with respect to the previous ones, /// and push it to the pending list. void sequence(hard_event &ev); + // Use this instead of flush() if `queued_events_mutex` is acquired. + void flush_unlocked(); cl_command_queue_properties props; pipe_context *pipe;