diff --git a/opencl/source/cl_device/cl_device.cpp b/opencl/source/cl_device/cl_device.cpp index 9caf1861ce..0009231daf 100644 --- a/opencl/source/cl_device/cl_device.cpp +++ b/opencl/source/cl_device/cl_device.cpp @@ -29,7 +29,9 @@ ClDevice::ClDevice(Device &device, Platform *platform) : device(device), platfor auto osInterface = getRootDeviceEnvironment().osInterface.get(); driverInfo.reset(DriverInfo::create(&device.getHardwareInfo(), osInterface)); initializeCaps(); - compilerExtensions = convertEnabledExtensionsToCompilerInternalOptions(deviceInfo.deviceExtensions); + OpenClCFeaturesContainer emptyOpenClCFeatures; + compilerExtensions = convertEnabledExtensionsToCompilerInternalOptions(deviceInfo.deviceExtensions, emptyOpenClCFeatures); + compilerExtensionsWithFeatures = convertEnabledExtensionsToCompilerInternalOptions(deviceInfo.deviceExtensions, deviceInfo.openclCFeatures); compilerFeatures = convertEnabledOclCFeaturesToCompilerInternalOptions(deviceInfo.openclCFeatures); auto numAvailableDevices = device.getNumAvailableDevices(); @@ -179,6 +181,9 @@ void ClDeviceVector::toDeviceIDs(std::vector &devIDs) { const std::string &ClDevice::peekCompilerExtensions() const { return compilerExtensions; } +const std::string &ClDevice::peekCompilerExtensionsWithFeatures() const { + return compilerExtensionsWithFeatures; +} const std::string &ClDevice::peekCompilerFeatures() const { return compilerFeatures; } diff --git a/opencl/source/cl_device/cl_device.h b/opencl/source/cl_device/cl_device.h index ea5b4b92ee..93101526a5 100644 --- a/opencl/source/cl_device/cl_device.h +++ b/opencl/source/cl_device/cl_device.h @@ -117,6 +117,7 @@ class ClDevice : public BaseObject<_cl_device_id> { const DeviceInfo &getSharedDeviceInfo() const; ClDevice *getDeviceById(uint32_t deviceId); const std::string &peekCompilerExtensions() const; + const std::string &peekCompilerExtensionsWithFeatures() const; const std::string &peekCompilerFeatures() const; std::unique_ptr syncBufferHandler; DeviceBitfield getDeviceBitfield() const; @@ -146,6 +147,7 @@ class ClDevice : public BaseObject<_cl_device_id> { std::vector simultaneousInterops = {0}; std::string compilerExtensions; + std::string compilerExtensionsWithFeatures; std::string compilerFeatures; }; diff --git a/opencl/source/cl_device/cl_device_info.h b/opencl/source/cl_device/cl_device_info.h index 70ee6fa703..30f4f253b8 100644 --- a/opencl/source/cl_device/cl_device_info.h +++ b/opencl/source/cl_device/cl_device_info.h @@ -15,12 +15,14 @@ namespace NEO { +using OpenClCFeaturesContainer = StackVec; + // clang-format off struct ClDeviceInfo { cl_name_version ilsWithVersion[1]; StackVec builtInKernelsWithVersion; StackVec openclCAllVersions; - StackVec openclCFeatures; + OpenClCFeaturesContainer openclCFeatures; std::vector extensionsWithVersion; cl_device_type deviceType; size_t maxSliceCount; diff --git a/opencl/source/platform/extensions.cpp b/opencl/source/platform/extensions.cpp index db1e70ca52..fcf85eacd5 100644 --- a/opencl/source/platform/extensions.cpp +++ b/opencl/source/platform/extensions.cpp @@ -73,7 +73,7 @@ std::string getExtensionsList(const HardwareInfo &hwInfo) { return allExtensionsList; } -void getOpenclCFeaturesList(const HardwareInfo &hwInfo, StackVec &openclCFeatures) { +void getOpenclCFeaturesList(const HardwareInfo &hwInfo, OpenClCFeaturesContainer &openclCFeatures) { cl_name_version openClCFeature; openClCFeature.version = CL_MAKE_VERSION(3, 0, 0); @@ -139,29 +139,31 @@ void getOpenclCFeaturesList(const HardwareInfo &hwInfo, StackVec 0) { - if (*processedString.rbegin() == ' ') { - processedString.pop_back(); - } - } - return processedString; -} +std::string convertEnabledExtensionsToCompilerInternalOptions(const char *enabledExtensions, + OpenClCFeaturesContainer &openclCFeatures) { -std::string convertEnabledExtensionsToCompilerInternalOptions(const char *enabledExtensions) { std::string extensionsList = enabledExtensions; - extensionsList.reserve(1000); - removeLastSpace(extensionsList); - std::string::size_type pos = 0; - while ((pos = extensionsList.find(" ", pos)) != std::string::npos) { - extensionsList.replace(pos, 1, ",+"); + extensionsList.reserve(1500); + extensionsList = " -cl-ext=-all,"; + std::istringstream extensionsStringStream(enabledExtensions); + std::string extension; + while (extensionsStringStream >> extension) { + extensionsList.append("+"); + extensionsList.append(extension); + extensionsList.append(","); } - extensionsList = " -cl-ext=-all,+" + extensionsList + ",+cl_khr_3d_image_writes "; + extensionsList.append("+cl_khr_3d_image_writes,"); + for (auto &feature : openclCFeatures) { + extensionsList.append("+"); + extensionsList.append(feature.name); + extensionsList.append(","); + } + extensionsList[extensionsList.size() - 1] = ' '; return extensionsList; } -std::string convertEnabledOclCFeaturesToCompilerInternalOptions(StackVec &openclCFeatures) { +std::string convertEnabledOclCFeaturesToCompilerInternalOptions(OpenClCFeaturesContainer &openclCFeatures) { UNRECOVERABLE_IF(openclCFeatures.empty()); std::string featuresList; featuresList.reserve(500); diff --git a/opencl/source/platform/extensions.h b/opencl/source/platform/extensions.h index 4d2e469215..7489e2efa6 100644 --- a/opencl/source/platform/extensions.h +++ b/opencl/source/platform/extensions.h @@ -10,7 +10,7 @@ #include "shared/source/helpers/hw_info.h" #include "shared/source/utilities/stackvec.h" -#include "CL/cl.h" +#include "opencl/source/cl_device/cl_device_info.h" #include @@ -21,9 +21,9 @@ constexpr const char *const sharingFormatQuery = "cl_intel_sharing_format_query extern const char *deviceExtensionsList; std::string getExtensionsList(const HardwareInfo &hwInfo); -void getOpenclCFeaturesList(const HardwareInfo &hwInfo, StackVec &openclCFeatures); -std::string removeLastSpace(std::string &s); -std::string convertEnabledExtensionsToCompilerInternalOptions(const char *deviceExtensions); -std::string convertEnabledOclCFeaturesToCompilerInternalOptions(StackVec &openclCFeatures); +void getOpenclCFeaturesList(const HardwareInfo &hwInfo, OpenClCFeaturesContainer &openclCFeatures); +std::string convertEnabledExtensionsToCompilerInternalOptions(const char *deviceExtensions, + OpenClCFeaturesContainer &openclCFeatures); +std::string convertEnabledOclCFeaturesToCompilerInternalOptions(OpenClCFeaturesContainer &openclCFeatures); } // namespace NEO diff --git a/opencl/source/program/build.cpp b/opencl/source/program/build.cpp index c94ddd6d88..8fde04b028 100644 --- a/opencl/source/program/build.cpp +++ b/opencl/source/program/build.cpp @@ -9,6 +9,7 @@ #include "shared/source/device/device.h" #include "shared/source/device_binary_format/device_binary_formats.h" #include "shared/source/execution_environment/execution_environment.h" +#include "shared/source/helpers/compiler_options_parser.h" #include "shared/source/source_level_debugger/source_level_debugger.h" #include "shared/source/utilities/time_measure_wrapper.h" @@ -103,13 +104,20 @@ cl_int Program::build( auto clDevice = this->pDevice->getSpecializedDevice(); UNRECOVERABLE_IF(clDevice == nullptr); - auto compilerExtensionsOptions = clDevice->peekCompilerExtensions(); - if (internalOptions.find(compilerExtensionsOptions) == std::string::npos) { - CompilerOptions::concatenateAppend(internalOptions, compilerExtensionsOptions); - } - auto compilerFeaturesOptions = clDevice->peekCompilerFeatures(); - if (internalOptions.find(compilerFeaturesOptions) == std::string::npos) { - CompilerOptions::concatenateAppend(internalOptions, compilerFeaturesOptions); + if (requiresOpenClCFeatures(options)) { + auto compilerExtensionsWithFeaturesOptions = clDevice->peekCompilerExtensionsWithFeatures(); + if (internalOptions.find(compilerExtensionsWithFeaturesOptions) == std::string::npos) { + CompilerOptions::concatenateAppend(internalOptions, compilerExtensionsWithFeaturesOptions); + } + auto compilerFeaturesOptions = clDevice->peekCompilerFeatures(); + if (internalOptions.find(compilerFeaturesOptions) == std::string::npos) { + CompilerOptions::concatenateAppend(internalOptions, compilerFeaturesOptions); + } + } else { + auto compilerExtensionsOptions = clDevice->peekCompilerExtensions(); + if (internalOptions.find(compilerExtensionsOptions) == std::string::npos) { + CompilerOptions::concatenateAppend(internalOptions, compilerExtensionsOptions); + } } inputArgs.apiOptions = ArrayRef(options.c_str(), options.length()); diff --git a/opencl/source/program/compile.cpp b/opencl/source/program/compile.cpp index 889bf7c979..94de26fe9e 100644 --- a/opencl/source/program/compile.cpp +++ b/opencl/source/program/compile.cpp @@ -11,6 +11,7 @@ #include "shared/source/device_binary_format/elf/elf_encoder.h" #include "shared/source/device_binary_format/elf/ocl_elf.h" #include "shared/source/execution_environment/execution_environment.h" +#include "shared/source/helpers/compiler_options_parser.h" #include "shared/source/source_level_debugger/source_level_debugger.h" #include "opencl/source/cl_device/cl_device.h" @@ -131,10 +132,13 @@ cl_int Program::compile( // set parameters for compilation auto clDevice = this->pDevice->getSpecializedDevice(); UNRECOVERABLE_IF(clDevice == nullptr); - auto compilerExtensionsOptions = clDevice->peekCompilerExtensions(); - CompilerOptions::concatenateAppend(internalOptions, compilerExtensionsOptions); - auto compilerFeaturesOptions = clDevice->peekCompilerFeatures(); - CompilerOptions::concatenateAppend(internalOptions, compilerFeaturesOptions); + + if (requiresOpenClCFeatures(options)) { + CompilerOptions::concatenateAppend(internalOptions, clDevice->peekCompilerExtensionsWithFeatures()); + CompilerOptions::concatenateAppend(internalOptions, clDevice->peekCompilerFeatures()); + } else { + CompilerOptions::concatenateAppend(internalOptions, clDevice->peekCompilerExtensions()); + } if (isKernelDebugEnabled()) { std::string filename; diff --git a/opencl/source/program/program.cpp b/opencl/source/program/program.cpp index 58f9baa0b4..b4b14b0a81 100644 --- a/opencl/source/program/program.cpp +++ b/opencl/source/program/program.cpp @@ -13,6 +13,7 @@ #include "shared/source/device_binary_format/device_binary_formats.h" #include "shared/source/device_binary_format/elf/elf_encoder.h" #include "shared/source/device_binary_format/elf/ocl_elf.h" +#include "shared/source/helpers/compiler_options_parser.h" #include "shared/source/helpers/debug_helpers.h" #include "shared/source/helpers/hw_helper.h" #include "shared/source/helpers/string.h" @@ -32,8 +33,6 @@ namespace NEO { -const std::string Program::clOptNameClVer("-cl-std=CL"); - Program::Program(ExecutionEnvironment &executionEnvironment, Context *context, bool isBuiltIn, Device *device) : executionEnvironment(executionEnvironment), context(context), pDevice(device), @@ -403,11 +402,11 @@ void Program::cleanCurrentKernelInfo() { void Program::updateNonUniformFlag() { //Look for -cl-std=CL substring and extract value behind which can be 1.2 2.0 2.1 and convert to value - auto pos = options.find(clOptNameClVer); + auto pos = options.find(clStdOptionName); if (pos == std::string::npos) { programOptionVersion = 12u; //Default is 1.2 } else { - std::stringstream ss{options.c_str() + pos + clOptNameClVer.size()}; + std::stringstream ss{options.c_str() + pos + clStdOptionName.size()}; uint32_t majorV = 0u, minorV = 0u; char dot = 0u; ss >> majorV; diff --git a/opencl/source/program/program.h b/opencl/source/program/program.h index bc8bdb7f60..6ff660bdbd 100644 --- a/opencl/source/program/program.h +++ b/opencl/source/program/program.h @@ -289,8 +289,6 @@ class Program : public BaseObject<_cl_program> { MOCKABLE_VIRTUAL bool appendKernelDebugOptions(); void notifyDebuggerWithSourceCode(std::string &filename); - static const std::string clOptNameClVer; - cl_program_binary_type programBinaryType = CL_PROGRAM_BINARY_TYPE_NONE; bool isSpirV = false; diff --git a/opencl/test/unit_test/device/device_caps_tests.cpp b/opencl/test/unit_test/device/device_caps_tests.cpp index e5fc702844..5440aa1b98 100644 --- a/opencl/test/unit_test/device/device_caps_tests.cpp +++ b/opencl/test/unit_test/device/device_caps_tests.cpp @@ -46,6 +46,8 @@ struct DeviceGetCapsTest : public ::testing::Test { } void verifyOpenclCAllVersions(MockClDevice &clDevice) { + EXPECT_FALSE(clDevice.getDeviceInfo().openclCAllVersions.usesDynamicMem()); + for (auto &openclCVersion : clDevice.getDeviceInfo().openclCAllVersions) { EXPECT_STREQ("OpenCL C", openclCVersion.name); } @@ -67,6 +69,8 @@ struct DeviceGetCapsTest : public ::testing::Test { } void verifyOpenclCFeatures(MockClDevice &clDevice) { + EXPECT_FALSE(clDevice.getDeviceInfo().openclCFeatures.usesDynamicMem()); + for (auto &openclCFeature : clDevice.getDeviceInfo().openclCFeatures) { EXPECT_EQ(CL_MAKE_VERSION(3u, 0u, 0u), openclCFeature.version); } @@ -833,6 +837,8 @@ TEST_F(DeviceGetCapsTest, givenVmeRelatedFlagsSetWhenCapsAreCreatedThenDeviceRep UltClDeviceFactory deviceFactory{1, 0}; const auto &caps = deviceFactory.rootDevices[0]->getDeviceInfo(); + EXPECT_FALSE(caps.builtInKernelsWithVersion.usesDynamicMem()); + auto builtInKernelWithVersion = caps.builtInKernelsWithVersion.begin(); if (isVmeEnabled) { @@ -1053,6 +1059,45 @@ TEST(DeviceGetCaps, WhenCheckingCompilerFeaturesThenValueIsCorrect) { EXPECT_STREQ(expectedCompilerFeatures.c_str(), pClDevice->compilerFeatures.c_str()); } +TEST(DeviceGetCaps, WhenPeekingCompilerExtensionsThenCompilerExtensionsAreReturned) { + UltClDeviceFactory deviceFactory{1, 0}; + auto pClDevice = deviceFactory.rootDevices[0]; + EXPECT_EQ(&pClDevice->compilerExtensions, &pClDevice->peekCompilerExtensions()); +} + +TEST(DeviceGetCaps, WhenCheckingCompilerExtensionsThenValueIsCorrect) { + UltClDeviceFactory deviceFactory{1, 0}; + auto pClDevice = deviceFactory.rootDevices[0]; + OpenClCFeaturesContainer emptyOpenClCFeatures; + auto expectedCompilerExtensions = convertEnabledExtensionsToCompilerInternalOptions(pClDevice->deviceInfo.deviceExtensions, + emptyOpenClCFeatures); + EXPECT_STREQ(expectedCompilerExtensions.c_str(), pClDevice->compilerExtensions.c_str()); +} + +TEST(DeviceGetCaps, WhenPeekingCompilerExtensionsWithFeaturesThenCompilerExtensionsWithFeaturesAreReturned) { + UltClDeviceFactory deviceFactory{1, 0}; + auto pClDevice = deviceFactory.rootDevices[0]; + EXPECT_EQ(&pClDevice->compilerExtensionsWithFeatures, &pClDevice->peekCompilerExtensionsWithFeatures()); +} + +TEST(DeviceGetCaps, WhenCheckingCompilerExtensionsWithFeaturesThenValueIsCorrect) { + UltClDeviceFactory deviceFactory{1, 0}; + auto pClDevice = deviceFactory.rootDevices[0]; + auto expectedCompilerExtensions = convertEnabledExtensionsToCompilerInternalOptions(pClDevice->deviceInfo.deviceExtensions, + pClDevice->deviceInfo.openclCFeatures); + EXPECT_STREQ(expectedCompilerExtensions.c_str(), pClDevice->compilerExtensionsWithFeatures.c_str()); +} + +TEST(DeviceGetCaps, WhenComparingCompilerExtensionsAndCompilerExtensionsWithFeaturesThenValuesMatch) { + UltClDeviceFactory deviceFactory{1, 0}; + auto pClDevice = deviceFactory.rootDevices[0]; + auto compilerExtensions = pClDevice->compilerExtensions; + auto compilerExtensionsWithFeatures = pClDevice->compilerExtensionsWithFeatures; + + compilerExtensions.erase(compilerExtensions.size() - 1); + EXPECT_STREQ(compilerExtensions.c_str(), compilerExtensionsWithFeatures.substr(0, compilerExtensions.size()).c_str()); +} + TEST(DeviceGetCaps, givenOclVersionLessThan21WhenCapsAreCreatedThenDeviceReportsNoSupportedIlVersions) { DebugManagerStateRestore dbgRestorer; { diff --git a/opencl/test/unit_test/mocks/mock_cl_device.h b/opencl/test/unit_test/mocks/mock_cl_device.h index 18bfd07d6f..b0f958df80 100644 --- a/opencl/test/unit_test/mocks/mock_cl_device.h +++ b/opencl/test/unit_test/mocks/mock_cl_device.h @@ -25,6 +25,8 @@ extern CommandStreamReceiver *createCommandStream(ExecutionEnvironment &executio class MockClDevice : public ClDevice { public: using ClDevice::ClDevice; + using ClDevice::compilerExtensions; + using ClDevice::compilerExtensionsWithFeatures; using ClDevice::compilerFeatures; using ClDevice::deviceExtensions; using ClDevice::deviceInfo; diff --git a/opencl/test/unit_test/offline_compiler/offline_compiler_tests.cpp b/opencl/test/unit_test/offline_compiler/offline_compiler_tests.cpp index 4597fb969f..f860af0410 100644 --- a/opencl/test/unit_test/offline_compiler/offline_compiler_tests.cpp +++ b/opencl/test/unit_test/offline_compiler/offline_compiler_tests.cpp @@ -235,7 +235,7 @@ TEST_F(OfflineCompilerTests, GoodArgTest) { delete pOfflineCompiler; } -TEST_F(OfflineCompilerTests, TestExtensions) { +TEST_F(OfflineCompilerTests, WhenCompilingSourceThenCorrectExtensionsArePassed) { std::vector argv = { "ocloc", "-file", @@ -246,13 +246,39 @@ TEST_F(OfflineCompilerTests, TestExtensions) { auto mockOfflineCompiler = std::unique_ptr(new MockOfflineCompiler()); ASSERT_NE(nullptr, mockOfflineCompiler); mockOfflineCompiler->parseCommandLine(argv.size(), argv); + std::string internalOptions = mockOfflineCompiler->internalOptions; EXPECT_THAT(internalOptions, ::testing::HasSubstr(std::string("cl_khr_3d_image_writes"))); - StackVec openclCFeatures; + OpenClCFeaturesContainer openclCFeatures; getOpenclCFeaturesList(DEFAULT_PLATFORM::hwInfo, openclCFeatures); - auto expectedFeaturesOption = convertEnabledOclCFeaturesToCompilerInternalOptions(openclCFeatures); - EXPECT_THAT(internalOptions, ::testing::HasSubstr(expectedFeaturesOption)); + for (auto &feature : openclCFeatures) { + EXPECT_THAT(internalOptions, ::testing::Not(::testing::HasSubstr(std::string{feature.name}))); + } +} +TEST_F(OfflineCompilerTests, givenClStd30OptionWhenCompilingSourceThenCorrectExtensionsArePassed) { + std::vector argv = { + "ocloc", + "-file", + "test_files/copybuffer.cl", + "-device", + gEnvironment->devicePrefix.c_str(), + "-options", + "-cl-std=CL3.0"}; + + auto mockOfflineCompiler = std::unique_ptr(new MockOfflineCompiler()); + ASSERT_NE(nullptr, mockOfflineCompiler); + mockOfflineCompiler->parseCommandLine(argv.size(), argv); + + std::string internalOptions = mockOfflineCompiler->internalOptions; + EXPECT_THAT(internalOptions, ::testing::HasSubstr(std::string("cl_khr_3d_image_writes"))); + + OpenClCFeaturesContainer openclCFeatures; + getOpenclCFeaturesList(DEFAULT_PLATFORM::hwInfo, openclCFeatures); + for (auto &feature : openclCFeatures) { + auto expectedRegex = std::string{feature.name} + ".*" + std::string{feature.name}; + EXPECT_THAT(internalOptions, ::testing::ContainsRegex(expectedRegex)); + } } TEST_F(OfflineCompilerTests, GoodBuildTest) { std::vector argv = { diff --git a/opencl/test/unit_test/platform/platform_tests.cpp b/opencl/test/unit_test/platform/platform_tests.cpp index 679f1fb93e..5c37e69f14 100644 --- a/opencl/test/unit_test/platform/platform_tests.cpp +++ b/opencl/test/unit_test/platform/platform_tests.cpp @@ -201,35 +201,54 @@ TEST(PlatformTestSimple, givenNotCsrHwTypeWhenPlatformIsInitializedThenInitAubCe } TEST(PlatformTestSimple, WhenConvertingCustomOclCFeaturesToCompilerInternalOptionsThenResultIsCorrect) { - StackVec customOpenclCFeatures; + OpenClCFeaturesContainer customOpenclCFeatures; cl_name_version feature; strcpy_s(feature.name, CL_NAME_VERSION_MAX_NAME_SIZE, "custom_feature"); customOpenclCFeatures.push_back(feature); auto compilerOption = convertEnabledOclCFeaturesToCompilerInternalOptions(customOpenclCFeatures); EXPECT_STREQ(" -cl-feature=+custom_feature ", compilerOption.c_str()); + compilerOption = convertEnabledExtensionsToCompilerInternalOptions("", customOpenclCFeatures); + EXPECT_STREQ(" -cl-ext=-all,+cl_khr_3d_image_writes,+custom_feature ", compilerOption.c_str()); strcpy_s(feature.name, CL_NAME_VERSION_MAX_NAME_SIZE, "other_extra_feature"); customOpenclCFeatures.push_back(feature); compilerOption = convertEnabledOclCFeaturesToCompilerInternalOptions(customOpenclCFeatures); EXPECT_STREQ(" -cl-feature=+custom_feature,+other_extra_feature ", compilerOption.c_str()); + compilerOption = convertEnabledExtensionsToCompilerInternalOptions("", customOpenclCFeatures); + EXPECT_STREQ(" -cl-ext=-all,+cl_khr_3d_image_writes,+custom_feature,+other_extra_feature ", compilerOption.c_str()); } TEST(PlatformTestSimple, WhenConvertingOclCFeaturesToCompilerInternalOptionsThenResultIsCorrect) { UltClDeviceFactory deviceFactory{1, 0}; auto pClDevice = deviceFactory.rootDevices[0]; - std::string expectedCompilerOption = " -cl-feature="; - for (auto &openclCFeature : pClDevice->deviceInfo.openclCFeatures) { - expectedCompilerOption += "+"; - expectedCompilerOption += openclCFeature.name; - expectedCompilerOption += ","; - } - expectedCompilerOption.erase(expectedCompilerOption.size() - 1, 1); - expectedCompilerOption += " "; + { + std::string expectedCompilerOption = " -cl-feature="; + for (auto &openclCFeature : pClDevice->deviceInfo.openclCFeatures) { + expectedCompilerOption += "+"; + expectedCompilerOption += openclCFeature.name; + expectedCompilerOption += ","; + } + expectedCompilerOption.erase(expectedCompilerOption.size() - 1, 1); + expectedCompilerOption += " "; - auto compilerOption = convertEnabledOclCFeaturesToCompilerInternalOptions(pClDevice->deviceInfo.openclCFeatures); - EXPECT_STREQ(expectedCompilerOption.c_str(), compilerOption.c_str()); + auto compilerOption = convertEnabledOclCFeaturesToCompilerInternalOptions(pClDevice->deviceInfo.openclCFeatures); + EXPECT_STREQ(expectedCompilerOption.c_str(), compilerOption.c_str()); + } + { + std::string expectedCompilerOption = " -cl-ext=-all,+cl_khr_3d_image_writes,"; + for (auto &openclCFeature : pClDevice->deviceInfo.openclCFeatures) { + expectedCompilerOption += "+"; + expectedCompilerOption += openclCFeature.name; + expectedCompilerOption += ","; + } + expectedCompilerOption.erase(expectedCompilerOption.size() - 1, 1); + expectedCompilerOption += " "; + + auto compilerOption = convertEnabledExtensionsToCompilerInternalOptions("", pClDevice->deviceInfo.openclCFeatures); + EXPECT_STREQ(expectedCompilerOption.c_str(), compilerOption.c_str()); + } } namespace NEO { @@ -274,8 +293,10 @@ TEST_F(PlatformTest, givenSupportingCl21WhenPlatformSupportsFp64ThenFillMatching const HardwareInfo *hwInfo; hwInfo = defaultHwInfo.get(); std::string extensionsList = getExtensionsList(*hwInfo); + OpenClCFeaturesContainer features; + getOpenclCFeaturesList(*hwInfo, features); - std::string compilerExtensions = convertEnabledExtensionsToCompilerInternalOptions(extensionsList.c_str()); + std::string compilerExtensions = convertEnabledExtensionsToCompilerInternalOptions(extensionsList.c_str(), features); EXPECT_THAT(compilerExtensions, ::testing::HasSubstr(std::string(" -cl-ext=-all,+cl"))); if (hwInfo->capabilityTable.supportsOcl21Features) { @@ -312,11 +333,13 @@ TEST_F(PlatformTest, givenNotSupportingCl21WhenPlatformNotSupportFp64ThenNotFill TesthwInfo.capabilityTable.supportsOcl21Features = false; std::string extensionsList = getExtensionsList(TesthwInfo); + OpenClCFeaturesContainer features; + getOpenclCFeaturesList(*defaultHwInfo, features); if (TesthwInfo.capabilityTable.supportsImages) { EXPECT_THAT(extensionsList, ::testing::HasSubstr(std::string("cl_khr_3d_image_writes"))); } - std::string compilerExtensions = convertEnabledExtensionsToCompilerInternalOptions(extensionsList.c_str()); + std::string compilerExtensions = convertEnabledExtensionsToCompilerInternalOptions(extensionsList.c_str(), features); EXPECT_THAT(compilerExtensions, ::testing::HasSubstr(std::string("-cl-ext=-all,+cl"))); EXPECT_THAT(compilerExtensions, ::testing::Not(::testing::HasSubstr(std::string("cl_khr_fp64")))); @@ -329,7 +352,9 @@ TEST_F(PlatformTest, givenFtrSupportAtomicsWhenCreateExtentionsListThenGetMatchi const HardwareInfo *hwInfo; hwInfo = defaultHwInfo.get(); std::string extensionsList = getExtensionsList(*hwInfo); - std::string compilerExtensions = convertEnabledExtensionsToCompilerInternalOptions(extensionsList.c_str()); + OpenClCFeaturesContainer features; + getOpenclCFeaturesList(*hwInfo, features); + std::string compilerExtensions = convertEnabledExtensionsToCompilerInternalOptions(extensionsList.c_str(), features); if (hwInfo->capabilityTable.ftrSupportsInteger64BitAtomics) { EXPECT_THAT(compilerExtensions, ::testing::HasSubstr(std::string("cl_khr_int64_base_atomics"))); @@ -346,7 +371,9 @@ TEST_F(PlatformTest, givenSupporteImagesAndClVersion21WhenCreateExtentionsListTh hwInfo.capabilityTable.clVersionSupport = 21; hwInfo.capabilityTable.supportsOcl21Features = true; std::string extensionsList = getExtensionsList(hwInfo); - std::string compilerExtensions = convertEnabledExtensionsToCompilerInternalOptions(extensionsList.c_str()); + OpenClCFeaturesContainer features; + getOpenclCFeaturesList(*defaultHwInfo, features); + std::string compilerExtensions = convertEnabledExtensionsToCompilerInternalOptions(extensionsList.c_str(), features); EXPECT_THAT(compilerExtensions, testing::HasSubstr(std::string("cl_intel_spirv_media_block_io"))); } @@ -356,24 +383,13 @@ TEST_F(PlatformTest, givenNotSupporteImagesAndClVersion21WhenCreateExtentionsLis hwInfo.capabilityTable.supportsImages = false; hwInfo.capabilityTable.clVersionSupport = 21; std::string extensionsList = getExtensionsList(hwInfo); - std::string compilerExtensions = convertEnabledExtensionsToCompilerInternalOptions(extensionsList.c_str()); + OpenClCFeaturesContainer features; + getOpenclCFeaturesList(*defaultHwInfo, features); + std::string compilerExtensions = convertEnabledExtensionsToCompilerInternalOptions(extensionsList.c_str(), features); EXPECT_THAT(compilerExtensions, testing::Not(testing::HasSubstr(std::string("cl_intel_spirv_media_block_io")))); } -TEST_F(PlatformTest, WhenRemovingLastSpaceThenStringDoesNotEndWithSpace) { - std::string emptyString = ""; - removeLastSpace(emptyString); - EXPECT_EQ(std::string(""), emptyString); - - std::string xString = "x"; - removeLastSpace(xString); - EXPECT_EQ(std::string("x"), xString); - - std::string xSpaceString = "x "; - removeLastSpace(xSpaceString); - EXPECT_EQ(std::string("x"), xSpaceString); -} TEST(PlatformConstructionTest, givenPlatformConstructorWhenItIsCalledTwiceThenTheSamePlatformIsReturned) { platformsImpl->clear(); auto platform1 = constructPlatform(); diff --git a/opencl/test/unit_test/program/program_tests.cpp b/opencl/test/unit_test/program/program_tests.cpp index f1b7849e93..74bae0a354 100644 --- a/opencl/test/unit_test/program/program_tests.cpp +++ b/opencl/test/unit_test/program/program_tests.cpp @@ -864,19 +864,44 @@ TEST_P(ProgramFromSourceTest, CreateWithSource_Build_Options_Duplicate) { EXPECT_EQ(CL_SUCCESS, retVal); } -TEST_P(ProgramFromSourceTest, WhenBuildingProgramThenFeaturesOptionIsAdded) { +TEST_P(ProgramFromSourceTest, WhenBuildingProgramThenFeaturesOptionIsNotAdded) { auto featuresOption = static_cast(devices[0])->peekCompilerFeatures(); EXPECT_THAT(pProgram->getInternalOptions(), testing::Not(testing::HasSubstr(featuresOption))); retVal = pProgram->build(1, devices, nullptr, nullptr, nullptr, false); EXPECT_EQ(CL_SUCCESS, retVal); + EXPECT_THAT(pProgram->getInternalOptions(), testing::Not(testing::HasSubstr(featuresOption))); +} + +TEST_P(ProgramFromSourceTest, WhenBuildingProgramWithOpenClC30ThenFeaturesOptionIsAdded) { + auto featuresOption = static_cast(devices[0])->peekCompilerFeatures(); + EXPECT_THAT(pProgram->getInternalOptions(), testing::Not(testing::HasSubstr(featuresOption))); + + auto cip = new MockCompilerInterfaceCaptureBuildOptions(); + auto pClDevice = pContext->getDevice(0); + pClDevice->getExecutionEnvironment()->rootDeviceEnvironments[pClDevice->getRootDeviceIndex()]->compilerInterface.reset(cip); + auto pProgram = std::make_unique(*pClDevice->getExecutionEnvironment()); + pProgram->setDevice(&pClDevice->getDevice()); + pProgram->sourceCode = "__kernel mock() {}"; + pProgram->createdFrom = Program::CreatedFrom::SOURCE; + + retVal = pProgram->build(1, devices, "-cl-std=CL3.0", nullptr, nullptr, false); + EXPECT_EQ(CL_SUCCESS, retVal); EXPECT_THAT(pProgram->getInternalOptions(), testing::HasSubstr(featuresOption)); } -TEST_P(ProgramFromSourceTest, WhenBuildingProgramThenFeaturesOptionIsAddedOnlyOnce) { - retVal = pProgram->build(1, devices, nullptr, nullptr, nullptr, false); +TEST_P(ProgramFromSourceTest, WhenBuildingProgramWithOpenClC30ThenFeaturesOptionIsAddedOnlyOnce) { + auto cip = new MockCompilerInterfaceCaptureBuildOptions(); + auto pClDevice = pContext->getDevice(0); + pClDevice->getExecutionEnvironment()->rootDeviceEnvironments[pClDevice->getRootDeviceIndex()]->compilerInterface.reset(cip); + auto pProgram = std::make_unique(*pClDevice->getExecutionEnvironment()); + pProgram->setDevice(&pClDevice->getDevice()); + pProgram->sourceCode = "__kernel mock() {}"; + pProgram->createdFrom = Program::CreatedFrom::SOURCE; + + retVal = pProgram->build(0, nullptr, "-cl-std=CL3.0", nullptr, nullptr, false); EXPECT_EQ(CL_SUCCESS, retVal); - retVal = pProgram->build(1, devices, nullptr, nullptr, nullptr, false); + retVal = pProgram->build(0, nullptr, "-cl-std=CL3.0", nullptr, nullptr, false); EXPECT_EQ(CL_SUCCESS, retVal); auto expectedFeaturesOption = static_cast(devices[0])->peekCompilerFeatures(); @@ -888,7 +913,7 @@ TEST_P(ProgramFromSourceTest, WhenBuildingProgramThenFeaturesOptionIsAddedOnlyOn EXPECT_EQ(std::string::npos, pos); } -TEST_P(ProgramFromSourceTest, WhenCompilingProgramThenFeaturesOptionIsAdded) { +TEST_P(ProgramFromSourceTest, WhenCompilingProgramThenFeaturesOptionIsNotAdded) { auto pCompilerInterface = new MockCompilerInterfaceCaptureBuildOptions(); auto pClDevice = static_cast(devices[0]); pClDevice->getExecutionEnvironment()->rootDeviceEnvironments[pClDevice->getRootDeviceIndex()]->compilerInterface.reset(pCompilerInterface); @@ -897,6 +922,23 @@ TEST_P(ProgramFromSourceTest, WhenCompilingProgramThenFeaturesOptionIsAdded) { retVal = pProgram->compile(1, devices, nullptr, 0, nullptr, nullptr, nullptr, nullptr); EXPECT_EQ(CL_SUCCESS, retVal); + EXPECT_THAT(pCompilerInterface->buildInternalOptions, testing::Not(testing::HasSubstr(featuresOption))); +} + +TEST_P(ProgramFromSourceTest, WhenCompilingProgramWithOpenClC30ThenFeaturesOptionIsAdded) { + auto pCompilerInterface = new MockCompilerInterfaceCaptureBuildOptions(); + auto pClDevice = pContext->getDevice(0); + pClDevice->getExecutionEnvironment()->rootDeviceEnvironments[pClDevice->getRootDeviceIndex()]->compilerInterface.reset(pCompilerInterface); + auto pProgram = std::make_unique(*pClDevice->getExecutionEnvironment()); + pProgram->setDevice(&pClDevice->getDevice()); + pProgram->sourceCode = "__kernel mock() {}"; + pProgram->createdFrom = Program::CreatedFrom::SOURCE; + + auto featuresOption = pClDevice->peekCompilerFeatures(); + EXPECT_THAT(pCompilerInterface->buildInternalOptions, testing::Not(testing::HasSubstr(featuresOption))); + + retVal = pProgram->compile(1, devices, "-cl-std=CL3.0", 0, nullptr, nullptr, nullptr, nullptr); + EXPECT_EQ(CL_SUCCESS, retVal); EXPECT_THAT(pCompilerInterface->buildInternalOptions, testing::HasSubstr(featuresOption)); } diff --git a/shared/offline_compiler/source/CMakeLists.txt b/shared/offline_compiler/source/CMakeLists.txt index a703e7b4e0..0d94f33a2f 100644 --- a/shared/offline_compiler/source/CMakeLists.txt +++ b/shared/offline_compiler/source/CMakeLists.txt @@ -24,6 +24,8 @@ set(CLOC_LIB_SRCS_LIB ${NEO_SHARED_DIRECTORY}/device_binary_format/elf/elf_encoder.h ${NEO_SHARED_DIRECTORY}/device_binary_format/elf/ocl_elf.h ${NEO_SHARED_DIRECTORY}/helpers/abort.cpp + ${NEO_SHARED_DIRECTORY}/helpers/compiler_options_parser.cpp + ${NEO_SHARED_DIRECTORY}/helpers/compiler_options_parser.h ${NEO_SHARED_DIRECTORY}/helpers/debug_helpers.cpp ${NEO_SHARED_DIRECTORY}/helpers/file_io.cpp ${NEO_SHARED_DIRECTORY}/helpers/hw_info.cpp diff --git a/shared/offline_compiler/source/offline_compiler.cpp b/shared/offline_compiler/source/offline_compiler.cpp index f141b60a15..fd4fb48fca 100644 --- a/shared/offline_compiler/source/offline_compiler.cpp +++ b/shared/offline_compiler/source/offline_compiler.cpp @@ -11,6 +11,7 @@ #include "shared/source/device_binary_format/device_binary_formats.h" #include "shared/source/device_binary_format/elf/elf_encoder.h" #include "shared/source/device_binary_format/elf/ocl_elf.h" +#include "shared/source/helpers/compiler_options_parser.h" #include "shared/source/helpers/debug_helpers.h" #include "shared/source/helpers/file_io.h" #include "shared/source/helpers/hw_info.h" @@ -556,11 +557,18 @@ int OfflineCompiler::parseCommandLine(size_t numArgs, const std::vectorprintf("Error: Cannot get HW Info for device %s.\n", deviceName.c_str()); } else { std::string extensionsList = getExtensionsList(hwInfo); - CompilerOptions::concatenateAppend(internalOptions, convertEnabledExtensionsToCompilerInternalOptions(extensionsList.c_str())); - - StackVec openclCFeatures; - getOpenclCFeaturesList(hwInfo, openclCFeatures); - CompilerOptions::concatenateAppend(internalOptions, convertEnabledOclCFeaturesToCompilerInternalOptions(openclCFeatures)); + if (requiresOpenClCFeatures(options)) { + OpenClCFeaturesContainer openclCFeatures; + getOpenclCFeaturesList(hwInfo, openclCFeatures); + auto compilerExtensions = convertEnabledExtensionsToCompilerInternalOptions(extensionsList.c_str(), openclCFeatures); + auto compilerFeatures = convertEnabledOclCFeaturesToCompilerInternalOptions(openclCFeatures); + CompilerOptions::concatenateAppend(internalOptions, compilerExtensions); + CompilerOptions::concatenateAppend(internalOptions, compilerFeatures); + } else { + OpenClCFeaturesContainer emptyOpenClCFeatures; + auto compilerExtensions = convertEnabledExtensionsToCompilerInternalOptions(extensionsList.c_str(), emptyOpenClCFeatures); + CompilerOptions::concatenateAppend(internalOptions, compilerExtensions); + } } } } diff --git a/shared/source/helpers/CMakeLists.txt b/shared/source/helpers/CMakeLists.txt index 2a2b8800bb..01e0eb6c8e 100644 --- a/shared/source/helpers/CMakeLists.txt +++ b/shared/source/helpers/CMakeLists.txt @@ -21,6 +21,8 @@ set(NEO_CORE_HELPERS ${CMAKE_CURRENT_SOURCE_DIR}/cache_policy.cpp ${CMAKE_CURRENT_SOURCE_DIR}/cache_policy.h ${CMAKE_CURRENT_SOURCE_DIR}/common_types.h + ${CMAKE_CURRENT_SOURCE_DIR}/compiler_options_parser.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/compiler_options_parser.h ${CMAKE_CURRENT_SOURCE_DIR}/completion_stamp.cpp ${CMAKE_CURRENT_SOURCE_DIR}/completion_stamp.h ${CMAKE_CURRENT_SOURCE_DIR}/constants.h diff --git a/shared/source/helpers/compiler_options_parser.cpp b/shared/source/helpers/compiler_options_parser.cpp new file mode 100644 index 0000000000..f486f837a5 --- /dev/null +++ b/shared/source/helpers/compiler_options_parser.cpp @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2020 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#include "shared/source/helpers/compiler_options_parser.h" + +#include +#include + +namespace NEO { + +const std::string clStdOptionName = "-cl-std=CL"; + +bool requiresOpenClCFeatures(const std::string &compileOptions) { + auto clStdValuePosition = compileOptions.find(clStdOptionName); + if (clStdValuePosition == std::string::npos) { + return false; + } + std::stringstream ss{compileOptions.c_str() + clStdValuePosition + clStdOptionName.size()}; + uint32_t majorVersion; + ss >> majorVersion; + return (majorVersion >= 3); +} + +} // namespace NEO diff --git a/shared/source/helpers/compiler_options_parser.h b/shared/source/helpers/compiler_options_parser.h new file mode 100644 index 0000000000..db9cd3daa6 --- /dev/null +++ b/shared/source/helpers/compiler_options_parser.h @@ -0,0 +1,18 @@ +/* + * Copyright (C) 2020 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#pragma once + +#include + +namespace NEO { + +extern const std::string clStdOptionName; + +bool requiresOpenClCFeatures(const std::string &compileOptions); + +} // namespace NEO