fix: generate SPIR-V for first device with -spv_only and multiple devices

If the family is provided as a device with the "-spv_only" flag, then
the SPIR-V file will be generated for the first device in the family.

Related-to: NEO-11550
Signed-off-by: Alicja Lukaszewicz <alicja.lukaszewicz@intel.com>
This commit is contained in:
Alicja Lukaszewicz
2024-06-27 14:44:13 +00:00
committed by Compute-Runtime-Automation
parent c5f0d3152d
commit 3db2bfc235
5 changed files with 125 additions and 2 deletions

View File

@@ -22,6 +22,7 @@
#include "environment.h" #include "environment.h"
#include "gtest/gtest.h" #include "gtest/gtest.h"
#include "hw_cmds_default.h" #include "hw_cmds_default.h"
#include "platforms.h"
#include <algorithm> #include <algorithm>
#include <array> #include <array>
@@ -624,6 +625,61 @@ TEST(OclocApiTests, GivenMissingFileNameWhenDecodingThenErrorIsReturned) {
EXPECT_EQ(-1, retVal); 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<OclocArgHelper> argHelper = std::make_unique<OclocArgHelper>();
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) { TEST(OclocApiTests, GivenHelpParameterWhenCompilingThenHelpMsgIsPrintedAndSuccessIsReturned) {
const char *argv[] = { const char *argv[] = {
"ocloc", "ocloc",

View File

@@ -142,6 +142,12 @@ static auto findAcronymForEnum(const EqComparableT &lhs) {
return [&lhs](const auto &rhs) { return lhs == rhs.second; }; return [&lhs](const auto &rhs) { return lhs == rhs.second; };
} }
TEST(OclocFatBinaryIsSpvOnly, givenSpvOnlyProvidedReturnsTrue) {
std::vector<std::string> args = {"-spv_only"};
EXPECT_TRUE(NEO::isSpvOnly(args));
}
TEST(OclocFatBinaryRequestedFatBinary, WhenDeviceArgMissingThenReturnsFalse) { TEST(OclocFatBinaryRequestedFatBinary, WhenDeviceArgMissingThenReturnsFalse) {
const char *args[] = {"ocloc", "-aaa", "*", "-device", "*"}; const char *args[] = {"ocloc", "-aaa", "*", "-device", "*"};
@@ -2192,6 +2198,38 @@ TEST(OclocFatBinaryHelpersTest, givenQuietModeWhenBuildingFatbinaryForTargetThen
EXPECT_TRUE(output.empty()) << output; EXPECT_TRUE(output.empty()) << output;
} }
TEST(OclocFatBinaryHelpersTest, WhenDeviceArgIsPresentReturnsCorrectIndex) {
std::vector<std::string> args = {
"ocloc",
"-file",
clFiles + "copybuffer.cl",
"-device",
gEnvironment->devicePrefix.c_str()};
EXPECT_EQ(4, getDeviceArgValueIdx(args));
}
TEST(OclocFatBinaryHelpersTest, WhenDeviceArgIsLastReturnsMinusOne) {
std::vector<std::string> args = {
"ocloc",
"-file",
clFiles + "copybuffer.cl",
"-device"};
EXPECT_EQ(-1, getDeviceArgValueIdx(args));
}
TEST(OclocFatBinaryHelpersTest, WhenDeviceArgIsAbsentReturnsMinusOne) {
std::vector<std::string> args = {
"ocloc",
"-file",
clFiles + "copybuffer.cl"};
EXPECT_EQ(-1, getDeviceArgValueIdx(args));
}
TEST(OclocFatBinaryHelpersTest, WhenArgsAreEmptyReturnsMinusOne) {
std::vector<std::string> args = {};
EXPECT_EQ(-1, getDeviceArgValueIdx(args));
}
TEST_P(OclocFatbinaryPerProductTests, givenReleaseWhenGetTargetProductsForFarbinaryThenCorrectAcronymsAreReturned) { TEST_P(OclocFatbinaryPerProductTests, givenReleaseWhenGetTargetProductsForFarbinaryThenCorrectAcronymsAreReturned) {
auto aotInfos = argHelper->productConfigHelper->getDeviceAotInfo(); auto aotInfos = argHelper->productConfigHelper->getDeviceAotInfo();
std::vector<NEO::ConstStringRef> expected{}; std::vector<NEO::ConstStringRef> expected{};

View File

@@ -31,6 +31,11 @@
#include <set> #include <set>
namespace NEO { namespace NEO {
bool isSpvOnly(const std::vector<std::string> &args) {
return std::find(args.begin(), args.end(), "-spv_only") != args.end();
}
bool requestedFatBinary(ConstStringRef deviceArg, OclocArgHelper *helper) { bool requestedFatBinary(ConstStringRef deviceArg, OclocArgHelper *helper) {
auto deviceName = deviceArg.str(); auto deviceName = deviceArg.str();
ProductConfigHelper::adjustDeviceName(deviceName); ProductConfigHelper::adjustDeviceName(deviceName);
@@ -266,6 +271,17 @@ std::vector<ConstStringRef> getTargetProductsForFatbinary(ConstStringRef deviceA
return retVal; return retVal;
} }
int getDeviceArgValueIdx(const std::vector<std::string> &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<int>(argIndex + 1);
}
}
return -1;
}
int buildFatBinaryForTarget(int retVal, const std::vector<std::string> &argsCopy, std::string pointerSize, Ar::ArEncoder &fatbinary, int buildFatBinaryForTarget(int retVal, const std::vector<std::string> &argsCopy, std::string pointerSize, Ar::ArEncoder &fatbinary,
OfflineCompiler *pCompiler, OclocArgHelper *argHelper, const std::string &product) { OfflineCompiler *pCompiler, OclocArgHelper *argHelper, const std::string &product) {

View File

@@ -23,6 +23,7 @@ struct ArEncoder;
} }
class OfflineCompiler; class OfflineCompiler;
bool isSpvOnly(const std::vector<std::string> &args);
bool requestedFatBinary(ConstStringRef deviceArg, OclocArgHelper *helper); bool requestedFatBinary(ConstStringRef deviceArg, OclocArgHelper *helper);
bool requestedFatBinary(const std::vector<std::string> &args, OclocArgHelper *helper); bool requestedFatBinary(const std::vector<std::string> &args, OclocArgHelper *helper);
inline bool requestedFatBinary(int argc, const char *argv[], 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); return requestedFatBinary(args, helper);
} }
int getDeviceArgValueIdx(const std::vector<std::string> &args);
int buildFatBinary(const std::vector<std::string> &args, OclocArgHelper *argHelper); int buildFatBinary(const std::vector<std::string> &args, OclocArgHelper *argHelper);
inline int buildFatBinary(int argc, const char *argv[], OclocArgHelper *argHelper) { inline int buildFatBinary(int argc, const char *argv[], OclocArgHelper *argHelper) {
std::vector<std::string> args; std::vector<std::string> args;

View File

@@ -119,13 +119,24 @@ void printOclocOptionsReadFromFile(OclocArgHelper &wrapper, OfflineCompiler *pCo
namespace Commands { namespace Commands {
int compile(OclocArgHelper *argHelper, const std::vector<std::string> &args) { int compile(OclocArgHelper *argHelper, const std::vector<std::string> &args) {
std::vector<std::string> argsCopy(args);
if (NEO::requestedFatBinary(args, argHelper)) { if (NEO::requestedFatBinary(args, argHelper)) {
return NEO::buildFatBinary(args, argHelper); bool onlySpirV = NEO::isSpvOnly(args);
if (onlySpirV) {
int deviceArgIndex = NEO::getDeviceArgValueIdx(args);
std::vector<ConstStringRef> 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; int retVal = OCLOC_SUCCESS;
std::unique_ptr<OfflineCompiler> pCompiler{OfflineCompiler::create(argsCopy.size(), argsCopy, true, retVal, argHelper)};
std::unique_ptr<OfflineCompiler> pCompiler{OfflineCompiler::create(args.size(), args, true, retVal, argHelper)};
if (retVal == OCLOC_SUCCESS) { if (retVal == OCLOC_SUCCESS) {
if (pCompiler->showHelpOnly()) { if (pCompiler->showHelpOnly()) {
return retVal; return retVal;