Skip to content

Commit

Permalink
feat(zebin): get extended args metadata on clGetKernelArgInfo API call
Browse files Browse the repository at this point in the history
This commit adds support for retrieving extended args metadata passed in
.kernel_misc_info zeInfo's section on clGetKernelArgInfo call.

Related-To: NEO-7372
Signed-off-by: Kacper Nowak <[email protected]>
  • Loading branch information
km-nowak authored and Compute-Runtime-Automation committed Nov 3, 2022
1 parent b284b72 commit 709e322
Show file tree
Hide file tree
Showing 7 changed files with 275 additions and 15 deletions.
5 changes: 5 additions & 0 deletions opencl/source/kernel/kernel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -483,6 +483,11 @@ cl_int Kernel::getArgInfo(cl_uint argIndex, cl_kernel_arg_info paramName, size_t
return retVal;
}

program->callPopulateZebinExtendedArgsMetadataOnce(clDevice.getRootDeviceIndex());
if (kernelInfo.kernelDescriptor.explicitArgsExtendedMetadata.empty()) {
return CL_KERNEL_ARG_INFO_NOT_AVAILABLE;
}

const auto &argTraits = args[argIndex].getTraits();
const auto &argMetadata = kernelInfo.kernelDescriptor.explicitArgsExtendedMetadata[argIndex];

Expand Down
19 changes: 19 additions & 0 deletions opencl/source/program/process_device_binary.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
*/

#include "shared/source/device_binary_format/device_binary_formats.h"
#include "shared/source/device_binary_format/zebin_decoder.h"
#include "shared/source/helpers/aligned_memory.h"
#include "shared/source/helpers/debug_helpers.h"
#include "shared/source/helpers/ptr_math.h"
Expand Down Expand Up @@ -248,6 +249,7 @@ cl_int Program::processProgramInfo(ProgramInfo &src, const ClDevice &clDevice) {
buildInfos[rootDeviceIndex].globalVarTotalSize = 0u;
}
}
buildInfos[rootDeviceIndex].kernelMiscInfoPos = src.kernelMiscInfoPos;

for (auto &kernelInfo : kernelInfoArray) {
cl_int retVal = CL_SUCCESS;
Expand Down Expand Up @@ -346,4 +348,21 @@ void Program::notifyDebuggerWithDebugData(ClDevice *clDevice) {
}
}
}

void Program::callPopulateZebinExtendedArgsMetadataOnce(uint32_t rootDeviceIndex) {
auto &buildInfo = this->buildInfos[rootDeviceIndex];
auto extractAndDecodeMetadata = [&]() {
auto refBin = ArrayRef<const uint8_t>(reinterpret_cast<const uint8_t *>(buildInfo.unpackedDeviceBinary.get()), buildInfo.unpackedDeviceBinarySize);
if (false == NEO::isDeviceBinaryFormat<NEO::DeviceBinaryFormat::Zebin>(refBin)) {
return;
}
std::string errors{}, warnings{};
auto metadataString = extractZeInfoMetadataStringFromZebin(refBin, errors, warnings);
auto decodeError = decodeAndPopulateKernelMiscInfo(buildInfo.kernelMiscInfoPos, buildInfo.kernelInfoArray, metadataString, errors, warnings);
if (NEO::DecodeError::Success != decodeError) {
PRINT_DEBUG_STRING(NEO::DebugManager.flags.PrintDebugMessages.get(), stderr, "Error in decodeAndPopulateKernelMiscInfo: %s\n", errors.c_str());
}
};
std::call_once(extractAndDecodeMetadataOnce, extractAndDecodeMetadata);
}
} // namespace NEO
4 changes: 4 additions & 0 deletions opencl/source/program/program.h
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,7 @@ class Program : public BaseObject<_cl_program> {
void notifyDebuggerWithDebugData(ClDevice *clDevice);
MOCKABLE_VIRTUAL void createDebugZebin(uint32_t rootDeviceIndex);
Debug::Segments getZebinSegments(uint32_t rootDeviceIndex);
void callPopulateZebinExtendedArgsMetadataOnce(uint32_t rootDeviceIndex);

protected:
MOCKABLE_VIRTUAL cl_int createProgramFromBinary(const void *pBinary, size_t binarySize, ClDevice &clDevice);
Expand Down Expand Up @@ -356,6 +357,7 @@ class Program : public BaseObject<_cl_program> {

std::unique_ptr<char[]> debugData;
size_t debugDataSize = 0U;
size_t kernelMiscInfoPos = std::string::npos;
};

std::vector<BuildInfo> buildInfos;
Expand All @@ -375,6 +377,8 @@ class Program : public BaseObject<_cl_program> {
uint32_t maxRootDeviceIndex = std::numeric_limits<uint32_t>::max();
std::mutex lockMutex;
uint32_t exposedKernels = 0;

std::once_flag extractAndDecodeMetadataOnce;
};

} // namespace NEO
166 changes: 166 additions & 0 deletions opencl/test/unit_test/kernel/kernel_arg_info_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include "shared/test/common/fixtures/memory_management_fixture.h"
#include "shared/test/common/helpers/kernel_binary_helper.h"
#include "shared/test/common/test_macros/test.h"
#include <shared/test/common/mocks/mock_modules_zebin.h>

#include "opencl/source/kernel/kernel.h"
#include "opencl/test/unit_test/fixtures/cl_device_fixture.h"
Expand Down Expand Up @@ -208,3 +209,168 @@ TEST_F(KernelArgInfoTest, GivenParamWhenGettingKernelArgNameThenCorrectValueIsRe
EXPECT_EQ(0, strcmp(paramValue, expectedArgName));
delete[] paramValue;
}

TEST_F(KernelArgInfoTest, givenNonZebinBinaryAndNoExplicitArgsMetadataWhenQueryingArgsInfoThenReturnError) {
constexpr auto mockDeviceBinarySize = 0x10;
uint8_t mockDeviceBinary[mockDeviceBinarySize]{0};

auto &buildInfo = pProgram->buildInfos[rootDeviceIndex];
buildInfo.unpackedDeviceBinary.reset(reinterpret_cast<char *>(mockDeviceBinary));
buildInfo.unpackedDeviceBinarySize = mockDeviceBinarySize;
ASSERT_FALSE(NEO::isDeviceBinaryFormat<NEO::DeviceBinaryFormat::Zebin>(ArrayRef<uint8_t>::fromAny(mockDeviceBinary, mockDeviceBinarySize)));

auto &kernelDescriptor = const_cast<KernelDescriptor &>(pKernel->getDescriptor());
kernelDescriptor.explicitArgsExtendedMetadata.clear();
ASSERT_TRUE(kernelDescriptor.explicitArgsExtendedMetadata.empty());

retVal = pKernel->getArgInfo(
0,
CL_KERNEL_ARG_NAME,
0,
nullptr,
0);

EXPECT_EQ(CL_KERNEL_ARG_INFO_NOT_AVAILABLE, retVal);
buildInfo.unpackedDeviceBinary.release();
}

TEST_F(KernelArgInfoTest, givenZebinBinaryAndErrorOnRetrievingArgsMetadataFromKernelsMiscInfoWhenQueryingArgsInfoThenReturnError) {
ZebinTestData::ValidEmptyProgram zebin;
ASSERT_TRUE(isDeviceBinaryFormat<NEO::DeviceBinaryFormat::Zebin>(ArrayRef<const uint8_t>::fromAny(zebin.storage.data(), zebin.storage.size())));

auto &buildInfo = pProgram->buildInfos[rootDeviceIndex];
buildInfo.unpackedDeviceBinary.reset(reinterpret_cast<char *>(zebin.storage.data()));
buildInfo.unpackedDeviceBinarySize = zebin.storage.size();
ASSERT_EQ(std::string::npos, buildInfo.kernelMiscInfoPos);

auto &kernelDescriptor = const_cast<KernelDescriptor &>(pKernel->getDescriptor());
kernelDescriptor.explicitArgsExtendedMetadata.clear();
ASSERT_TRUE(kernelDescriptor.explicitArgsExtendedMetadata.empty());

retVal = pKernel->getArgInfo(
0,
CL_KERNEL_ARG_NAME,
0,
nullptr,
0);

EXPECT_EQ(CL_KERNEL_ARG_INFO_NOT_AVAILABLE, retVal);
buildInfo.unpackedDeviceBinary.release();
}

TEST_F(KernelArgInfoTest, givenZebinBinaryWithProperKernelsMiscInfoAndNoExplicitArgsMetadataWhenQueryingArgInfoThenRetrieveItFromKernelsMiscInfo) {
std::string zeInfo = R"===('
kernels:
- name: CopyBuffer
execution_env:
simd_size: 32
payload_arguments:
- arg_type: arg_bypointer
offset: 0
size: 0
arg_index: 0
addrmode: stateful
addrspace: global
access_type: readwrite
- arg_type: arg_bypointer
offset: 32
size: 8
arg_index: 0
addrmode: stateless
addrspace: global
access_type: readwrite
- arg_type: enqueued_local_size
offset: 40
size: 12
kernels_misc_info:
- name: CopyBuffer
args_info:
- index: 0
name: a
address_qualifier: __global
access_qualifier: NONE
type_name: 'int*;8'
type_qualifiers: NONE
)===";
std::vector<uint8_t> storage;
MockElfEncoder<> elfEncoder;
auto &elfHeader = elfEncoder.getElfFileHeader();
elfHeader.type = NEO::Elf::ET_ZEBIN_EXE;
elfHeader.machine = pProgram->getExecutionEnvironment().rootDeviceEnvironments[rootDeviceIndex]->getHardwareInfo()->platform.eProductFamily;
const uint8_t testKernelData[0x10] = {0u};

elfEncoder.appendSection(NEO::Elf::SHT_PROGBITS, NEO::Elf::SectionsNamesZebin::textPrefix.str() + "CopyBuffer", testKernelData);
elfEncoder.appendSection(NEO::Elf::SHT_ZEBIN_ZEINFO, NEO::Elf::SectionsNamesZebin::zeInfo, zeInfo);
storage = elfEncoder.encode();
elfHeader = *reinterpret_cast<NEO::Elf::ElfFileHeader<NEO::Elf::EI_CLASS_64> *>(storage.data());

auto &buildInfo = pProgram->buildInfos[rootDeviceIndex];

//set kernels_misc_info pos manually, as we are not invoking decodeZebin() or processProgramInfo() in this test
ProgramInfo programInfo;
setKernelMiscInfoPosition(zeInfo, programInfo);
buildInfo.kernelMiscInfoPos = programInfo.kernelMiscInfoPos;
buildInfo.unpackedDeviceBinary.reset(reinterpret_cast<char *>(storage.data()));
buildInfo.unpackedDeviceBinarySize = storage.size();

auto &kernelDescriptor = const_cast<KernelDescriptor &>(pKernel->getDescriptor());
kernelDescriptor.explicitArgsExtendedMetadata.clear();
ASSERT_TRUE(kernelDescriptor.explicitArgsExtendedMetadata.empty());

std::array<cl_kernel_arg_info, 5> paramNames = {
CL_KERNEL_ARG_NAME,
CL_KERNEL_ARG_ADDRESS_QUALIFIER,
CL_KERNEL_ARG_ACCESS_QUALIFIER,
CL_KERNEL_ARG_TYPE_NAME,
CL_KERNEL_ARG_TYPE_QUALIFIER,
};
cl_uint argInd = 0;
constexpr size_t maxParamValueSize{0x10};
size_t paramValueSize = 0;
size_t paramValueSizeRet = 0;

for (const auto &paramName : paramNames) {
char paramValue[maxParamValueSize]{0};

retVal = pKernel->getArgInfo(
argInd,
paramName,
paramValueSize,
nullptr,
&paramValueSizeRet);
EXPECT_NE(0u, paramValueSizeRet);
ASSERT_EQ(CL_SUCCESS, retVal);

ASSERT_LT(paramValueSizeRet, maxParamValueSize);
paramValueSize = paramValueSizeRet;

retVal = pKernel->getArgInfo(
argInd,
paramName,
paramValueSize,
paramValue,
nullptr);
ASSERT_EQ(CL_SUCCESS, retVal);
switch (paramName) {
case (CL_KERNEL_ARG_NAME):
EXPECT_EQ(0, strcmp(paramValue, "a"));
break;
case (CL_KERNEL_ARG_ADDRESS_QUALIFIER):
EXPECT_EQ(*(reinterpret_cast<cl_kernel_arg_address_qualifier *>(paramValue)), static_cast<cl_uint>(CL_KERNEL_ARG_ADDRESS_GLOBAL));
break;
case (CL_KERNEL_ARG_ACCESS_QUALIFIER):
EXPECT_EQ(*(reinterpret_cast<cl_kernel_arg_access_qualifier *>(paramValue)), static_cast<cl_uint>(CL_KERNEL_ARG_ACCESS_NONE));
break;
case (CL_KERNEL_ARG_TYPE_NAME):
EXPECT_EQ(0, strcmp(paramValue, "'int*;8'"));
break;
case (CL_KERNEL_ARG_TYPE_QUALIFIER):
EXPECT_EQ(*(reinterpret_cast<cl_kernel_arg_type_qualifier *>(paramValue)), static_cast<cl_ulong>(CL_KERNEL_ARG_TYPE_NONE));
break;
default:
ASSERT_TRUE(false);
break;
}
}
buildInfo.unpackedDeviceBinary.release();
}
26 changes: 22 additions & 4 deletions shared/source/device_binary_format/zebin_decoder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1609,12 +1609,12 @@ void populateKernelMiscInfo(KernelDescriptor &dst, KernelMiscArgInfos &kernelMis
}
}

NEO::DecodeError decodeAndPopulateKernelMiscInfo(ProgramInfo &dst, ConstStringRef metadataString, std::string &outErrReason, std::string &outWarning) {
if (std::string::npos == dst.kernelMiscInfoPos) {
NEO::DecodeError decodeAndPopulateKernelMiscInfo(size_t kernelMiscInfoOffset, std::vector<NEO::KernelInfo *> &kernelInfos, ConstStringRef metadataString, std::string &outErrReason, std::string &outWarning) {
if (std::string::npos == kernelMiscInfoOffset) {
outErrReason.append("DeviceBinaryFormat::Zebin : Position of " + Elf::ZebinKernelMetadata::Tags::kernelMiscInfo.str() + " not set - may be missing in zeInfo.\n");
return DecodeError::InvalidBinary;
}
ConstStringRef kernelMiscInfoString(reinterpret_cast<const char *>(metadataString.begin() + dst.kernelMiscInfoPos), metadataString.size() - dst.kernelMiscInfoPos);
ConstStringRef kernelMiscInfoString(reinterpret_cast<const char *>(metadataString.begin() + kernelMiscInfoOffset), metadataString.size() - kernelMiscInfoOffset);
NEO::KernelInfo *kernelInfo = nullptr;

NEO::Yaml::YamlParser parser;
Expand Down Expand Up @@ -1651,7 +1651,7 @@ NEO::DecodeError decodeAndPopulateKernelMiscInfo(ProgramInfo &dst, ConstStringRe
return DecodeError::InvalidBinary;
}
for (auto &[kName, miscInfos] : kernelArgsMiscInfoVec) {
for (auto dstKernelInfo : dst.kernelInfos) {
for (auto dstKernelInfo : kernelInfos) {
if (dstKernelInfo->kernelDescriptor.kernelMetadata.kernelName == kName) {
kernelInfo = dstKernelInfo;
break;
Expand Down Expand Up @@ -1810,4 +1810,22 @@ NEO::DecodeError decodeZebin(ProgramInfo &dst, NEO::Elf::Elf<numBits> &elf, std:
return DecodeError::Success;
}

template <Elf::ELF_IDENTIFIER_CLASS numBits>
ConstStringRef extractZeInfoMetadataString(const ArrayRef<const uint8_t> zebin, std::string &outErrReason, std::string &outWarning) {
auto decodedElf = NEO::Elf::decodeElf<numBits>(zebin, outErrReason, outWarning);
for (const auto &sectionHeader : decodedElf.sectionHeaders) {
if (sectionHeader.header->type == NEO::Elf::SHT_ZEBIN_ZEINFO) {
auto zeInfoData = sectionHeader.data;
return ConstStringRef{reinterpret_cast<const char *>(zeInfoData.begin()), zeInfoData.size()};
}
}
return ConstStringRef{};
}

ConstStringRef extractZeInfoMetadataStringFromZebin(const ArrayRef<const uint8_t> zebin, std::string &outErrReason, std::string &outWarning) {
return Elf::isElf<Elf::EI_CLASS_32>(zebin)
? extractZeInfoMetadataString<Elf::EI_CLASS_32>(zebin, outErrReason, outWarning)
: extractZeInfoMetadataString<Elf::EI_CLASS_64>(zebin, outErrReason, outWarning);
}

} // namespace NEO
5 changes: 4 additions & 1 deletion shared/source/device_binary_format/zebin_decoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include "shared/source/device_binary_format/elf/zebin_elf.h"
#include "shared/source/device_binary_format/yaml/yaml_parser.h"
#include "shared/source/kernel/kernel_descriptor.h"
#include "shared/source/program/kernel_info.h"
#include "shared/source/utilities/stackvec.h"

#include <string>
Expand Down Expand Up @@ -153,6 +154,8 @@ NEO::DecodeError readKernelMiscArgumentInfos(const NEO::Yaml::YamlParser &parser

void populateKernelMiscInfo(KernelDescriptor &dst, KernelMiscArgInfos &kernelMiscArgInfosVec, std::string &outErrReason, std::string &outWarning);

NEO::DecodeError decodeAndPopulateKernelMiscInfo(ProgramInfo &dst, ConstStringRef metadataString, std::string &outErrReason, std::string &outWarning);
NEO::DecodeError decodeAndPopulateKernelMiscInfo(size_t kernelMiscInfoOffset, std::vector<NEO::KernelInfo *> &kernelInfos, ConstStringRef metadataString, std::string &outErrReason, std::string &outWarning);

ConstStringRef extractZeInfoMetadataStringFromZebin(const ArrayRef<const uint8_t> zebin, std::string &outErrReason, std::string &outWarning);

} // namespace NEO
Loading

0 comments on commit 709e322

Please sign in to comment.