diff options
author | Michael Meeks <michael.meeks@collabora.com> | 2016-07-11 15:12:38 +0100 |
---|---|---|
committer | Jan Holesovsky <kendy@collabora.com> | 2016-07-12 15:33:14 +0000 |
commit | 9befbe1f81a7930e167e0a711666b0779898c12e (patch) | |
tree | c0019b022343e41ed55940bfd84cc686a671183d | |
parent | e1ef22371613f384cc2f6fc75d022cb01bf92af7 (diff) |
desktop: validate OpenCL drivers before use.
OpenCL validation needs to happen before drivers are used in
anger. This should isolate any crashes, and/or mis-behavior to
We use app version, CL driver version and file time-stamp to
trigger re-testing the device. If anything fails: hard disable
OpenCL.
We use an opencl validation sheet (cl-test.ods) and install it.
It is a minimal CL set - it requires a very short formula group
length, and combines several CL functions into few formulae to
test more.
The sheet structure, in particular the manual squaring / SQRT is
necessary to stick within the default CL subset, and ensure that
formulae are CL enabled from the root of the dependency tree up.
Reviewed-on: https://gerrit.libreoffice.org/27131
Tested-by: Jenkins <ci@libreoffice.org>
Reviewed-by: Michael Meeks <michael.meeks@collabora.com>
(cherry picked from commit c44726c48228d9c6a5960e302b1c0bd16b0099c4)
+ opencl: bail out early in missing OpenCL case.
(cherry picked from commit 605a5dc088385ad21c33028d8107125c0316ddb1)
+ Remove bogus dependency from opencl to configmgr
Since f41eb66302208f384a475fb20c98b6d1b0676cb6 "opencl: OpenCLZone, detect CL
device change and disable CL on crash" vcl links against opencl (so indirectly
linked against configmgr), which caused CppunitTest_configmgr_unit to include
the configmgr object files both statically (through
gb_CppunitTest_use_library_objects) and through the linked-in configmgr dynamic
library, which in turn caused ASan builds to report an ODR violation for a
doubly defined 'typeinfo name for configmgr::Access'.
(cherry picked from commit 9c711f05fa10dc70e4257a1f48d43f539353541a)
Change-Id: I18682dbdf9a8ba9c16d52bad4447e9acce97f0a3
Reviewed-on: https://gerrit.libreoffice.org/27146
Reviewed-by: Jan Holesovsky <kendy@collabora.com>
Tested-by: Jenkins <ci@libreoffice.org>
-rw-r--r-- | Repository.mk | 1 | ||||
-rw-r--r-- | desktop/Library_sofficeapp.mk | 2 | ||||
-rw-r--r-- | desktop/inc/app.hxx | 1 | ||||
-rw-r--r-- | desktop/source/app/app.cxx | 5 | ||||
-rw-r--r-- | desktop/source/app/opencl.cxx | 174 | ||||
-rw-r--r-- | opencl/Library_opencl.mk | 1 | ||||
-rw-r--r-- | opencl/inc/opencl_device.hxx | 3 | ||||
-rw-r--r-- | opencl/source/OpenCLZone.cxx | 4 | ||||
-rw-r--r-- | opencl/source/openclwrapper.cxx | 6 | ||||
-rw-r--r-- | sc/Module_sc.mk | 1 | ||||
-rw-r--r-- | sc/Package_opencl.mk | 16 | ||||
-rw-r--r-- | sc/source/core/opencl/cl-test.ods | bin | 0 -> 18186 bytes | |||
-rw-r--r-- | sc/source/core/tool/formulagroup.cxx | 21 | ||||
-rw-r--r-- | solenv/gbuild/extensions/pre_MergedLibsList.mk | 1 |
14 files changed, 215 insertions, 21 deletions
diff --git a/Repository.mk b/Repository.mk index 04519cb5a52d..adfc34bded05 100644 --- a/Repository.mk +++ b/Repository.mk @@ -820,6 +820,7 @@ $(eval $(call gb_Helper_register_packages_for_install,ooo,\ vcl_opengl_blacklist \ ) \ $(if $(ENABLE_OPENGL_CANVAS),canvas_opengl_shader) \ + $(if $(filter OPENCL,$(BUILD_TYPE)),sc_opencl_runtimetest) \ )) $(eval $(call gb_Helper_register_packages_for_install,ogltrans,\ diff --git a/desktop/Library_sofficeapp.mk b/desktop/Library_sofficeapp.mk index ef95ecfbdc19..785ab24048d6 100644 --- a/desktop/Library_sofficeapp.mk +++ b/desktop/Library_sofficeapp.mk @@ -48,6 +48,7 @@ $(eval $(call gb_Library_use_libraries,sofficeapp,\ deploymentmisc \ editeng \ i18nlangtag \ + $(if $(filter OPENCL,$(BUILD_TYPE)),opencl) \ sal \ salhelper \ sb \ @@ -93,6 +94,7 @@ $(eval $(call gb_Library_add_exception_objects,sofficeapp,\ desktop/source/app/langselect \ desktop/source/app/lockfile2 \ desktop/source/app/officeipcthread \ + desktop/source/app/opencl \ desktop/source/app/sofficemain \ desktop/source/app/userinstall \ desktop/source/migration/migration \ diff --git a/desktop/inc/app.hxx b/desktop/inc/app.hxx index d07d2853da38..f9e7db6624ae 100644 --- a/desktop/inc/app.hxx +++ b/desktop/inc/app.hxx @@ -84,6 +84,7 @@ class Desktop : public Application static void OpenClients(); static void OpenDefault(); + static void CheckOpenCLCompute(const css::uno::Reference<css::frame::XDesktop2> &); DECL_STATIC_LINK_TYPED( Desktop, EnableAcceptors_Impl, void*, void); diff --git a/desktop/source/app/app.cxx b/desktop/source/app/app.cxx index 958ca8ac1121..1a47e8cc88f1 100644 --- a/desktop/source/app/app.cxx +++ b/desktop/source/app/app.cxx @@ -1573,6 +1573,11 @@ int Desktop::Main() FatalError( MakeStartupErrorMessage(e.Message) ); } + // FIXME: move this somewhere sensible. +#if HAVE_FEATURE_OPENCL + CheckOpenCLCompute(xDesktop); +#endif + // Release solar mutex just before we wait for our client to connect { SolarMutexReleaser aReleaser; diff --git a/desktop/source/app/opencl.cxx b/desktop/source/app/opencl.cxx new file mode 100644 index 000000000000..09f2204e07ca --- /dev/null +++ b/desktop/source/app/opencl.cxx @@ -0,0 +1,174 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +/* + * This module exists to validate the OpenCL implementation, + * where necessary during startup; and before we load or + * calculate using OpenCL. + */ + +#include "app.hxx" + +#include <config_version.h> +#include <config_folders.h> + +#include <rtl/bootstrap.hxx> + +#include <officecfg/Office/Calc.hxx> +#include <officecfg/Office/Common.hxx> + +#include <com/sun/star/table/XCell2.hpp> +#include <com/sun/star/sheet/XCalculatable.hpp> +#include <com/sun/star/sheet/XSpreadsheet.hpp> +#include <com/sun/star/sheet/XSpreadsheets.hpp> +#include <com/sun/star/sheet/XSpreadsheetDocument.hpp> + +#include <opencl/openclwrapper.hxx> +#include <opencl/OpenCLZone.hxx> + +#include <osl/file.hxx> + +using namespace ::osl; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::frame; + +namespace desktop { + +#if HAVE_FEATURE_OPENCL + +bool testOpenCLCompute(const Reference< XDesktop2 > &xDesktop, const OUString &rURL) +{ + bool bSuccess = false; + css::uno::Reference< css::lang::XComponent > xComponent; + + SAL_INFO("opencl", "Starting CL test spreadsheet"); + + try { + css::uno::Reference< css::frame::XComponentLoader > xLoader(xDesktop, css::uno::UNO_QUERY_THROW); + + css::uno::Sequence< css::beans::PropertyValue > aArgs(1); + aArgs[0].Name = "Hidden"; + aArgs[0].Value = makeAny(true); + + xComponent.set(xLoader->loadComponentFromURL(rURL, "_blank", 0, aArgs)); + + // What an unpleasant API to use. + css::uno::Reference< css::sheet::XCalculatable > xCalculatable( xComponent, css::uno::UNO_QUERY_THROW); + css::uno::Reference< css::sheet::XSpreadsheetDocument > xSpreadDoc( xComponent, css::uno::UNO_QUERY_THROW ); + css::uno::Reference< css::sheet::XSpreadsheets > xSheets( xSpreadDoc->getSheets(), css::uno::UNO_QUERY_THROW ); + css::uno::Reference< css::container::XIndexAccess > xIndex( xSheets, css::uno::UNO_QUERY_THROW ); + css::uno::Reference< css::sheet::XSpreadsheet > xSheet( xIndex->getByIndex(0), css::uno::UNO_QUERY_THROW); + + // So we insert our MAX call at the end on a named range. + css::uno::Reference< css::table::XCell2 > xThresh( xSheet->getCellByPosition(1,1), css::uno::UNO_QUERY_THROW ); // B2 + double fThreshold = xThresh->getValue(); + + // We need pure OCL formulae all the way through the + // dependency chain, or we fall-back. + xCalculatable->calculateAll(); + + // So we insert our MAX call at the end on a named range. + css::uno::Reference< css::table::XCell2 > xCell( xSheet->getCellByPosition(1,0), css::uno::UNO_QUERY_THROW ); + xCell->setFormula("=MAX(results)"); + double fResult = xCell->getValue(); + + // Ensure the maximum variance is below our tolerance. + if (fResult > fThreshold) + { + SAL_WARN("opencl", "OpenCL results unstable - disabling; result: " + << fResult << " vs. " << fThreshold); + } + else + { + SAL_INFO("opencl", "calculating smoothly; result: " << fResult); + bSuccess = true; + } + } + catch (const css::uno::Exception &e) + { + (void)e; + SAL_WARN("opencl", "OpenCL testing failed - disabling: " << e.Message); + } + + if (!bSuccess) + OpenCLZone::hardDisable(); + if (xComponent.is()) + xComponent->dispose(); + + return bSuccess; +} + +void Desktop::CheckOpenCLCompute(const Reference< XDesktop2 > &xDesktop) +{ + if (getenv("SAL_DISABLE_OPENCL") || + !officecfg::Office::Common::Misc::UseOpenCL::get()) + return; + + SAL_INFO("opencl", "Initiating test of OpenCL device"); + OpenCLZone aZone; + + OUString aDevice = officecfg::Office::Calc::Formula::Calculation::OpenCLDevice::get(); + OUString aSelectedCLDeviceVersionID; + if (!opencl::switchOpenCLDevice( + &aDevice, + officecfg::Office::Calc::Formula::Calculation::OpenCLAutoSelect::get(), + false /* bForceEvaluation */, + aSelectedCLDeviceVersionID)) + { + SAL_WARN("opencl", "Failed to initialize OpenCL for test"); + OpenCLZone::hardDisable(); + return; + } + + // Append our app version as well. + aSelectedCLDeviceVersionID += "--"; + aSelectedCLDeviceVersionID += LIBO_VERSION_DOTTED; + + // Append timestamp of the file. + OUString aURL("$BRAND_BASE_DIR/" LIBO_ETC_FOLDER "/opencl/cl-test.ods"); + rtl::Bootstrap::expandMacros(aURL); + + DirectoryItem aItem; + DirectoryItem::get( aURL, aItem ); + FileStatus aFileStatus( osl_FileStatus_Mask_ModifyTime ); + aItem.getFileStatus( aFileStatus ); + TimeValue aTimeVal = aFileStatus.getModifyTime(); + aSelectedCLDeviceVersionID += "--"; + aSelectedCLDeviceVersionID += OUString::number(aTimeVal.Seconds); + + if (aSelectedCLDeviceVersionID != officecfg::Office::Common::Misc::SelectedOpenCLDeviceIdentifier::get()) + { + // OpenCL device changed - sanity check it and disable if bad. + + boost::optional<sal_Int32> nOrigMinimumSize = officecfg::Office::Calc::Formula::Calculation::OpenCLMinimumDataSize::get(); + { // set the group size to something small for quick testing. + std::shared_ptr<comphelper::ConfigurationChanges> xBatch(comphelper::ConfigurationChanges::create()); + officecfg::Office::Calc::Formula::Calculation::OpenCLMinimumDataSize::set(3 /* small */, xBatch); + xBatch->commit(); + } + + bool bSucceeded = testOpenCLCompute(xDesktop, aURL); + + // it passed -> save the device. + { + std::shared_ptr<comphelper::ConfigurationChanges> xBatch(comphelper::ConfigurationChanges::create()); + officecfg::Office::Calc::Formula::Calculation::OpenCLMinimumDataSize::set(nOrigMinimumSize, xBatch); + // allow the user to subsequently manually enable it. + officecfg::Office::Common::Misc::SelectedOpenCLDeviceIdentifier::set(aSelectedCLDeviceVersionID, xBatch); + xBatch->commit(); + } + + if (!bSucceeded) + OpenCLZone::hardDisable(); + } +} +#endif // HAVE_FEATURE_OPENCL + +} // end namespace desktop + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/opencl/Library_opencl.mk b/opencl/Library_opencl.mk index 3d9b0325564c..927de0f81e59 100644 --- a/opencl/Library_opencl.mk +++ b/opencl/Library_opencl.mk @@ -34,7 +34,6 @@ $(eval $(call gb_Library_use_sdk_api,opencl)) $(eval $(call gb_Library_use_libraries,opencl,\ clew \ - configmgr \ comphelper \ cppu \ sal \ diff --git a/opencl/inc/opencl_device.hxx b/opencl/inc/opencl_device.hxx index 0963304e8f99..216af72de849 100644 --- a/opencl/inc/opencl_device.hxx +++ b/opencl/inc/opencl_device.hxx @@ -16,6 +16,9 @@ namespace opencl { ds_device getDeviceSelection(OUString const & pFileName, bool bForceSelection = false); +struct GPUEnv; +void releaseOpenCLEnv( GPUEnv *gpuInfo ); + } #endif diff --git a/opencl/source/OpenCLZone.cxx b/opencl/source/OpenCLZone.cxx index dc3a9522380b..03521a29c66f 100644 --- a/opencl/source/OpenCLZone.cxx +++ b/opencl/source/OpenCLZone.cxx @@ -7,7 +7,9 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include <opencl/openclwrapper.hxx> #include <opencl/OpenCLZone.hxx> +#include "opencl_device.hxx" #include <memory> @@ -40,6 +42,8 @@ void OpenCLZone::hardDisable() auto xConfProvider = css::configuration::theDefaultProvider::get(comphelper::getProcessComponentContext()); css::uno::Reference<css::util::XFlushable> xFlushable(xConfProvider, css::uno::UNO_QUERY_THROW); xFlushable->flush(); + + releaseOpenCLEnv(&opencl::gpuEnv); } } diff --git a/opencl/source/openclwrapper.cxx b/opencl/source/openclwrapper.cxx index 1af142c1476c..807a185ea5ff 100644 --- a/opencl/source/openclwrapper.cxx +++ b/opencl/source/openclwrapper.cxx @@ -269,6 +269,8 @@ bool initOpenCLAttr( OpenCLEnv * env ) return false; } +} + void releaseOpenCLEnv( GPUEnv *gpuInfo ) { OpenCLZone zone; @@ -299,6 +301,8 @@ void releaseOpenCLEnv( GPUEnv *gpuInfo ) return; } +namespace { + bool buildProgram(const char* buildOption, GPUEnv* gpuInfo, int idx) { cl_int clStatus; @@ -696,7 +700,7 @@ void findDeviceInfoFromDeviceId(cl_device_id aDeviceId, size_t& rDeviceId, size_ bool switchOpenCLDevice(const OUString* pDevice, bool bAutoSelect, bool bForceEvaluation, OUString& rOutSelectedDeviceVersionIDString) { - if(fillOpenCLInfo().empty()) + if(fillOpenCLInfo().empty() || getenv("SAL_DISABLE_OPENCL")) return false; cl_device_id pDeviceId = nullptr; diff --git a/sc/Module_sc.mk b/sc/Module_sc.mk index 3dcb39ad2c57..73019d616cdd 100644 --- a/sc/Module_sc.mk +++ b/sc/Module_sc.mk @@ -15,6 +15,7 @@ $(eval $(call gb_Module_add_targets,sc,\ Library_scd \ Library_scfilt \ $(call gb_Helper_optional,DESKTOP,Library_scui) \ + $(call gb_Helper_optional,OPENCL,Package_opencl) \ )) $(eval $(call gb_Module_add_l10n_targets,sc,\ diff --git a/sc/Package_opencl.mk b/sc/Package_opencl.mk new file mode 100644 index 000000000000..ef1579f52eb5 --- /dev/null +++ b/sc/Package_opencl.mk @@ -0,0 +1,16 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*- +# +# This file is part of the LibreOffice project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# + +$(eval $(call gb_Package_Package,sc_opencl_runtimetest,$(SRCDIR)/sc/source/core/opencl)) + +$(eval $(call gb_Package_add_files,sc_opencl_runtimetest,$(LIBO_ETC_FOLDER)/opencl,\ + cl-test.ods \ +)) + +# vim: set noet sw=4 ts=4: diff --git a/sc/source/core/opencl/cl-test.ods b/sc/source/core/opencl/cl-test.ods Binary files differnew file mode 100644 index 000000000000..8380e0b93a83 --- /dev/null +++ b/sc/source/core/opencl/cl-test.ods diff --git a/sc/source/core/tool/formulagroup.cxx b/sc/source/core/tool/formulagroup.cxx index abe92e89ec31..8f166ceeb190 100644 --- a/sc/source/core/tool/formulagroup.cxx +++ b/sc/source/core/tool/formulagroup.cxx @@ -338,26 +338,9 @@ bool FormulaGroupInterpreter::switchOpenCLDevice(const OUString& rDeviceId, bool return false; delete msInstance; - msInstance = nullptr; + msInstance = new sc::opencl::FormulaGroupInterpreterOpenCL(); - if (bOpenCLEnabled) - { - msInstance = new sc::opencl::FormulaGroupInterpreterOpenCL(); - - if (aSelectedCLDeviceVersionID != officecfg::Office::Common::Misc::SelectedOpenCLDeviceIdentifier::get()) - { - // perform OpenCL calculation tests - - // save the device - std::shared_ptr<comphelper::ConfigurationChanges> xBatch(comphelper::ConfigurationChanges::create()); - officecfg::Office::Common::Misc::SelectedOpenCLDeviceIdentifier::set(aSelectedCLDeviceVersionID, xBatch); - xBatch->commit(); - } - - return msInstance != nullptr; - } - - return false; + return true; } void FormulaGroupInterpreter::getOpenCLDeviceInfo(sal_Int32& rDeviceId, sal_Int32& rPlatformId) diff --git a/solenv/gbuild/extensions/pre_MergedLibsList.mk b/solenv/gbuild/extensions/pre_MergedLibsList.mk index b33857054965..20cc510ddaea 100644 --- a/solenv/gbuild/extensions/pre_MergedLibsList.mk +++ b/solenv/gbuild/extensions/pre_MergedLibsList.mk @@ -12,6 +12,7 @@ MERGE_LIBRARY_LIST := \ avmedia \ $(if $(filter $(OS),ANDROID),,basebmp) \ + $(if $(filter OPENCL,$(BUILD_TYPE)),clew) \ basegfx \ canvastools \ configmgr \ |