summaryrefslogtreecommitdiff
path: root/desktop/source/app/opencl.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'desktop/source/app/opencl.cxx')
-rw-r--r--desktop/source/app/opencl.cxx61
1 files changed, 60 insertions, 1 deletions
diff --git a/desktop/source/app/opencl.cxx b/desktop/source/app/opencl.cxx
index f62c93e32e1f..a728ba2b8b7d 100644
--- a/desktop/source/app/opencl.cxx
+++ b/desktop/source/app/opencl.cxx
@@ -38,6 +38,7 @@
#include <opencl/OpenCLZone.hxx>
#include <osl/file.hxx>
+#include <osl/process.h>
using namespace ::osl;
using namespace ::com::sun::star::uno;
@@ -47,6 +48,61 @@ namespace desktop {
#if HAVE_FEATURE_OPENCL
+static bool testOpenCLDriver()
+{
+ // A simple OpenCL test run in a separate process in order to test
+ // whether the driver crashes (asserts,etc.) when trying to use OpenCL.
+ SAL_INFO("opencl", "Starting CL driver test");
+
+ OUString testerURL("$BRAND_BASE_DIR/" LIBO_BIN_FOLDER "/opencltest");
+ rtl::Bootstrap::expandMacros(testerURL); //TODO: detect failure
+
+ OUString deviceName, platformName;
+ openclwrapper::getOpenCLDeviceName( deviceName, platformName );
+ rtl_uString* args[] = { deviceName.pData, platformName.pData };
+ sal_Int32 numArgs = 2;
+
+ oslProcess process;
+ oslSecurity security = osl_getCurrentSecurity();
+ oslProcessError error = osl_executeProcess(testerURL.pData, args, numArgs,
+ osl_Process_SEARCHPATH | osl_Process_HIDDEN, security,
+ nullptr, nullptr, 0, &process );
+ osl_freeSecurityHandle( security );
+ if( error != osl_Process_E_None )
+ {
+ SAL_WARN( "opencl", "failed to start CL driver test: " << error );
+ return false;
+ }
+ // If the driver takes more than 10 seconds, it's probably broken/useless.
+ TimeValue timeout( 10, 0 );
+ error = osl_joinProcessWithTimeout( process, &timeout );
+ if( error == osl_Process_E_None )
+ {
+ oslProcessInfo info;
+ info.Size = sizeof( info );
+ error = osl_getProcessInfo( process, osl_Process_EXITCODE, &info );
+ if( error == osl_Process_E_None )
+ {
+ if( info.Code == 0 )
+ {
+ SAL_INFO( "opencl", "CL driver test passed" );
+ osl_freeProcessHandle( process );
+ return true;
+ }
+ else
+ {
+ SAL_WARN( "opencl", "CL driver test failed - disabling: " << info.Code );
+ osl_freeProcessHandle( process );
+ return false;
+ }
+ }
+ }
+ SAL_WARN( "opencl", "CL driver test did not finish - disabling: " << error );
+ osl_terminateProcess( process );
+ osl_freeProcessHandle( process );
+ return false;
+}
+
static bool testOpenCLCompute(const Reference< XDesktop2 > &xDesktop, const OUString &rURL)
{
bool bSuccess = false;
@@ -178,7 +234,10 @@ void Desktop::CheckOpenCLCompute(const Reference< XDesktop2 > &xDesktop)
xBatch->commit();
}
- bool bSucceeded = testOpenCLCompute(xDesktop, aURL);
+ // Hopefully at least basic functionality always works and broken OpenCL implementations break
+ // only when they are used to compute something. If this assumptions turns out to be not true,
+ // the driver check needs to be moved sooner.
+ bool bSucceeded = testOpenCLDriver() && testOpenCLCompute(xDesktop, aURL);
{ // restore the minimum group size
std::shared_ptr<comphelper::ConfigurationChanges> xBatch(comphelper::ConfigurationChanges::create());