diff --git a/opencl/test/unit_test/offline_compiler/ocloc_api_tests.cpp b/opencl/test/unit_test/offline_compiler/ocloc_api_tests.cpp index ac3b90e326..17262b777a 100644 --- a/opencl/test/unit_test/offline_compiler/ocloc_api_tests.cpp +++ b/opencl/test/unit_test/offline_compiler/ocloc_api_tests.cpp @@ -22,6 +22,7 @@ #include "environment.h" #include "gtest/gtest.h" #include "hw_cmds_default.h" +#include "platforms.h" #include #include @@ -624,6 +625,61 @@ TEST(OclocApiTests, GivenMissingFileNameWhenDecodingThenErrorIsReturned) { EXPECT_EQ(-1, retVal); } +TEST(OclocApiTests, GivenOnlySpirVWithMultipleDevicesWhenCompilingThenFirstDeviceIsSelected) { + std::string clFileName(clFiles + "copybuffer.cl"); + AOT::FAMILY productFamily = AOT::UNKNOWN_FAMILY; + std::string familyAcronym(""); + std::string firstDeviceAcronym(""); + + std::unique_ptr argHelper = std::make_unique(); + auto supportedDeviceConfigs = argHelper->productConfigHelper->getDeviceAotInfo(); + if (supportedDeviceConfigs.empty()) { + GTEST_SKIP(); + } + + for (const auto &deviceConfig : supportedDeviceConfigs) { + if (deviceConfig.hwInfo->platform.eProductFamily == NEO::DEFAULT_PLATFORM::hwInfo.platform.eProductFamily) { + productFamily = deviceConfig.family; + familyAcronym = ProductConfigHelper::getAcronymFromAFamily(deviceConfig.family).str(); + break; + } + } + + if (familyAcronym.empty()) { + GTEST_SKIP(); + } + + const char *argv[] = { + "ocloc", + "-file", + clFileName.c_str(), + "-device", + familyAcronym.c_str(), + "-spv_only"}; + unsigned int argc = sizeof(argv) / sizeof(const char *); + + for (const auto &deviceConfig : supportedDeviceConfigs) { + if (deviceConfig.family == productFamily) { + if (!deviceConfig.deviceAcronyms.empty()) { + firstDeviceAcronym = deviceConfig.deviceAcronyms.front().str(); + } else if (!deviceConfig.rtlIdAcronyms.empty()) { + firstDeviceAcronym = deviceConfig.rtlIdAcronyms.front().str(); + } + break; + } + } + + testing::internal::CaptureStdout(); + int retVal = oclocInvoke(argc, argv, + 0, nullptr, nullptr, nullptr, + 0, nullptr, nullptr, nullptr, + nullptr, nullptr, nullptr, nullptr); + std::string output = testing::internal::GetCapturedStdout(); + + EXPECT_EQ(retVal, OCLOC_SUCCESS); + EXPECT_EQ(std::string::npos, output.find("Command was: ocloc -device " + firstDeviceAcronym + " -spv_only")); +} + TEST(OclocApiTests, GivenHelpParameterWhenCompilingThenHelpMsgIsPrintedAndSuccessIsReturned) { const char *argv[] = { "ocloc", diff --git a/opencl/test/unit_test/offline_compiler/ocloc_fatbinary_tests.cpp b/opencl/test/unit_test/offline_compiler/ocloc_fatbinary_tests.cpp index b72dc127c8..5a71573bae 100644 --- a/opencl/test/unit_test/offline_compiler/ocloc_fatbinary_tests.cpp +++ b/opencl/test/unit_test/offline_compiler/ocloc_fatbinary_tests.cpp @@ -142,6 +142,12 @@ static auto findAcronymForEnum(const EqComparableT &lhs) { return [&lhs](const auto &rhs) { return lhs == rhs.second; }; } +TEST(OclocFatBinaryIsSpvOnly, givenSpvOnlyProvidedReturnsTrue) { + std::vector args = {"-spv_only"}; + + EXPECT_TRUE(NEO::isSpvOnly(args)); +} + TEST(OclocFatBinaryRequestedFatBinary, WhenDeviceArgMissingThenReturnsFalse) { const char *args[] = {"ocloc", "-aaa", "*", "-device", "*"}; @@ -2192,6 +2198,38 @@ TEST(OclocFatBinaryHelpersTest, givenQuietModeWhenBuildingFatbinaryForTargetThen EXPECT_TRUE(output.empty()) << output; } +TEST(OclocFatBinaryHelpersTest, WhenDeviceArgIsPresentReturnsCorrectIndex) { + std::vector args = { + "ocloc", + "-file", + clFiles + "copybuffer.cl", + "-device", + gEnvironment->devicePrefix.c_str()}; + EXPECT_EQ(4, getDeviceArgValueIdx(args)); +} + +TEST(OclocFatBinaryHelpersTest, WhenDeviceArgIsLastReturnsMinusOne) { + std::vector args = { + "ocloc", + "-file", + clFiles + "copybuffer.cl", + "-device"}; + EXPECT_EQ(-1, getDeviceArgValueIdx(args)); +} + +TEST(OclocFatBinaryHelpersTest, WhenDeviceArgIsAbsentReturnsMinusOne) { + std::vector args = { + "ocloc", + "-file", + clFiles + "copybuffer.cl"}; + EXPECT_EQ(-1, getDeviceArgValueIdx(args)); +} + +TEST(OclocFatBinaryHelpersTest, WhenArgsAreEmptyReturnsMinusOne) { + std::vector args = {}; + EXPECT_EQ(-1, getDeviceArgValueIdx(args)); +} + TEST_P(OclocFatbinaryPerProductTests, givenReleaseWhenGetTargetProductsForFarbinaryThenCorrectAcronymsAreReturned) { auto aotInfos = argHelper->productConfigHelper->getDeviceAotInfo(); std::vector expected{}; diff --git a/shared/offline_compiler/source/ocloc_fatbinary.cpp b/shared/offline_compiler/source/ocloc_fatbinary.cpp index 0ac1035109..d25a8f61f9 100644 --- a/shared/offline_compiler/source/ocloc_fatbinary.cpp +++ b/shared/offline_compiler/source/ocloc_fatbinary.cpp @@ -31,6 +31,11 @@ #include namespace NEO { + +bool isSpvOnly(const std::vector &args) { + return std::find(args.begin(), args.end(), "-spv_only") != args.end(); +} + bool requestedFatBinary(ConstStringRef deviceArg, OclocArgHelper *helper) { auto deviceName = deviceArg.str(); ProductConfigHelper::adjustDeviceName(deviceName); @@ -266,6 +271,17 @@ std::vector getTargetProductsForFatbinary(ConstStringRef deviceA return retVal; } +int getDeviceArgValueIdx(const std::vector &args) { + for (size_t argIndex = 0; argIndex < args.size(); ++argIndex) { + const auto &currArg = args[argIndex]; + const bool hasMoreArgs = (argIndex + 1 < args.size()); + if ((ConstStringRef("-device") == currArg) && hasMoreArgs) { + return static_cast(argIndex + 1); + } + } + return -1; +} + int buildFatBinaryForTarget(int retVal, const std::vector &argsCopy, std::string pointerSize, Ar::ArEncoder &fatbinary, OfflineCompiler *pCompiler, OclocArgHelper *argHelper, const std::string &product) { diff --git a/shared/offline_compiler/source/ocloc_fatbinary.h b/shared/offline_compiler/source/ocloc_fatbinary.h index a833c3d516..7591f046de 100644 --- a/shared/offline_compiler/source/ocloc_fatbinary.h +++ b/shared/offline_compiler/source/ocloc_fatbinary.h @@ -23,6 +23,7 @@ struct ArEncoder; } class OfflineCompiler; +bool isSpvOnly(const std::vector &args); bool requestedFatBinary(ConstStringRef deviceArg, OclocArgHelper *helper); bool requestedFatBinary(const std::vector &args, OclocArgHelper *helper); inline bool requestedFatBinary(int argc, const char *argv[], OclocArgHelper *helper) { @@ -31,6 +32,7 @@ inline bool requestedFatBinary(int argc, const char *argv[], OclocArgHelper *hel return requestedFatBinary(args, helper); } +int getDeviceArgValueIdx(const std::vector &args); int buildFatBinary(const std::vector &args, OclocArgHelper *argHelper); inline int buildFatBinary(int argc, const char *argv[], OclocArgHelper *argHelper) { std::vector args; diff --git a/shared/offline_compiler/source/ocloc_interface.cpp b/shared/offline_compiler/source/ocloc_interface.cpp index a70d2267db..573764e9d0 100644 --- a/shared/offline_compiler/source/ocloc_interface.cpp +++ b/shared/offline_compiler/source/ocloc_interface.cpp @@ -119,13 +119,24 @@ void printOclocOptionsReadFromFile(OclocArgHelper &wrapper, OfflineCompiler *pCo namespace Commands { int compile(OclocArgHelper *argHelper, const std::vector &args) { + std::vector argsCopy(args); + if (NEO::requestedFatBinary(args, argHelper)) { - return NEO::buildFatBinary(args, argHelper); + bool onlySpirV = NEO::isSpvOnly(args); + + if (onlySpirV) { + int deviceArgIndex = NEO::getDeviceArgValueIdx(args); + std::vector targetProducts = NEO::getTargetProductsForFatbinary(ConstStringRef(args[deviceArgIndex]), argHelper); + ConstStringRef firstDevice = targetProducts.front(); + argsCopy[deviceArgIndex] = firstDevice.str(); + } else { + return NEO::buildFatBinary(args, argHelper); + } } int retVal = OCLOC_SUCCESS; + std::unique_ptr pCompiler{OfflineCompiler::create(argsCopy.size(), argsCopy, true, retVal, argHelper)}; - std::unique_ptr pCompiler{OfflineCompiler::create(args.size(), args, true, retVal, argHelper)}; if (retVal == OCLOC_SUCCESS) { if (pCompiler->showHelpOnly()) { return retVal;