Skip to content

Commit 709e322

Browse files
feat(zebin): get extended args metadata on clGetKernelArgInfo API call
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]>
1 parent b284b72 commit 709e322

File tree

7 files changed

+275
-15
lines changed

7 files changed

+275
-15
lines changed

Diff for: opencl/source/kernel/kernel.cpp

+5
Original file line numberDiff line numberDiff line change
@@ -483,6 +483,11 @@ cl_int Kernel::getArgInfo(cl_uint argIndex, cl_kernel_arg_info paramName, size_t
483483
return retVal;
484484
}
485485

486+
program->callPopulateZebinExtendedArgsMetadataOnce(clDevice.getRootDeviceIndex());
487+
if (kernelInfo.kernelDescriptor.explicitArgsExtendedMetadata.empty()) {
488+
return CL_KERNEL_ARG_INFO_NOT_AVAILABLE;
489+
}
490+
486491
const auto &argTraits = args[argIndex].getTraits();
487492
const auto &argMetadata = kernelInfo.kernelDescriptor.explicitArgsExtendedMetadata[argIndex];
488493

Diff for: opencl/source/program/process_device_binary.cpp

+19
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
*/
77

88
#include "shared/source/device_binary_format/device_binary_formats.h"
9+
#include "shared/source/device_binary_format/zebin_decoder.h"
910
#include "shared/source/helpers/aligned_memory.h"
1011
#include "shared/source/helpers/debug_helpers.h"
1112
#include "shared/source/helpers/ptr_math.h"
@@ -248,6 +249,7 @@ cl_int Program::processProgramInfo(ProgramInfo &src, const ClDevice &clDevice) {
248249
buildInfos[rootDeviceIndex].globalVarTotalSize = 0u;
249250
}
250251
}
252+
buildInfos[rootDeviceIndex].kernelMiscInfoPos = src.kernelMiscInfoPos;
251253

252254
for (auto &kernelInfo : kernelInfoArray) {
253255
cl_int retVal = CL_SUCCESS;
@@ -346,4 +348,21 @@ void Program::notifyDebuggerWithDebugData(ClDevice *clDevice) {
346348
}
347349
}
348350
}
351+
352+
void Program::callPopulateZebinExtendedArgsMetadataOnce(uint32_t rootDeviceIndex) {
353+
auto &buildInfo = this->buildInfos[rootDeviceIndex];
354+
auto extractAndDecodeMetadata = [&]() {
355+
auto refBin = ArrayRef<const uint8_t>(reinterpret_cast<const uint8_t *>(buildInfo.unpackedDeviceBinary.get()), buildInfo.unpackedDeviceBinarySize);
356+
if (false == NEO::isDeviceBinaryFormat<NEO::DeviceBinaryFormat::Zebin>(refBin)) {
357+
return;
358+
}
359+
std::string errors{}, warnings{};
360+
auto metadataString = extractZeInfoMetadataStringFromZebin(refBin, errors, warnings);
361+
auto decodeError = decodeAndPopulateKernelMiscInfo(buildInfo.kernelMiscInfoPos, buildInfo.kernelInfoArray, metadataString, errors, warnings);
362+
if (NEO::DecodeError::Success != decodeError) {
363+
PRINT_DEBUG_STRING(NEO::DebugManager.flags.PrintDebugMessages.get(), stderr, "Error in decodeAndPopulateKernelMiscInfo: %s\n", errors.c_str());
364+
}
365+
};
366+
std::call_once(extractAndDecodeMetadataOnce, extractAndDecodeMetadata);
367+
}
349368
} // namespace NEO

Diff for: opencl/source/program/program.h

+4
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,7 @@ class Program : public BaseObject<_cl_program> {
290290
void notifyDebuggerWithDebugData(ClDevice *clDevice);
291291
MOCKABLE_VIRTUAL void createDebugZebin(uint32_t rootDeviceIndex);
292292
Debug::Segments getZebinSegments(uint32_t rootDeviceIndex);
293+
void callPopulateZebinExtendedArgsMetadataOnce(uint32_t rootDeviceIndex);
293294

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

357358
std::unique_ptr<char[]> debugData;
358359
size_t debugDataSize = 0U;
360+
size_t kernelMiscInfoPos = std::string::npos;
359361
};
360362

361363
std::vector<BuildInfo> buildInfos;
@@ -375,6 +377,8 @@ class Program : public BaseObject<_cl_program> {
375377
uint32_t maxRootDeviceIndex = std::numeric_limits<uint32_t>::max();
376378
std::mutex lockMutex;
377379
uint32_t exposedKernels = 0;
380+
381+
std::once_flag extractAndDecodeMetadataOnce;
378382
};
379383

380384
} // namespace NEO

Diff for: opencl/test/unit_test/kernel/kernel_arg_info_tests.cpp

+166
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include "shared/test/common/fixtures/memory_management_fixture.h"
99
#include "shared/test/common/helpers/kernel_binary_helper.h"
1010
#include "shared/test/common/test_macros/test.h"
11+
#include <shared/test/common/mocks/mock_modules_zebin.h>
1112

1213
#include "opencl/source/kernel/kernel.h"
1314
#include "opencl/test/unit_test/fixtures/cl_device_fixture.h"
@@ -208,3 +209,168 @@ TEST_F(KernelArgInfoTest, GivenParamWhenGettingKernelArgNameThenCorrectValueIsRe
208209
EXPECT_EQ(0, strcmp(paramValue, expectedArgName));
209210
delete[] paramValue;
210211
}
212+
213+
TEST_F(KernelArgInfoTest, givenNonZebinBinaryAndNoExplicitArgsMetadataWhenQueryingArgsInfoThenReturnError) {
214+
constexpr auto mockDeviceBinarySize = 0x10;
215+
uint8_t mockDeviceBinary[mockDeviceBinarySize]{0};
216+
217+
auto &buildInfo = pProgram->buildInfos[rootDeviceIndex];
218+
buildInfo.unpackedDeviceBinary.reset(reinterpret_cast<char *>(mockDeviceBinary));
219+
buildInfo.unpackedDeviceBinarySize = mockDeviceBinarySize;
220+
ASSERT_FALSE(NEO::isDeviceBinaryFormat<NEO::DeviceBinaryFormat::Zebin>(ArrayRef<uint8_t>::fromAny(mockDeviceBinary, mockDeviceBinarySize)));
221+
222+
auto &kernelDescriptor = const_cast<KernelDescriptor &>(pKernel->getDescriptor());
223+
kernelDescriptor.explicitArgsExtendedMetadata.clear();
224+
ASSERT_TRUE(kernelDescriptor.explicitArgsExtendedMetadata.empty());
225+
226+
retVal = pKernel->getArgInfo(
227+
0,
228+
CL_KERNEL_ARG_NAME,
229+
0,
230+
nullptr,
231+
0);
232+
233+
EXPECT_EQ(CL_KERNEL_ARG_INFO_NOT_AVAILABLE, retVal);
234+
buildInfo.unpackedDeviceBinary.release();
235+
}
236+
237+
TEST_F(KernelArgInfoTest, givenZebinBinaryAndErrorOnRetrievingArgsMetadataFromKernelsMiscInfoWhenQueryingArgsInfoThenReturnError) {
238+
ZebinTestData::ValidEmptyProgram zebin;
239+
ASSERT_TRUE(isDeviceBinaryFormat<NEO::DeviceBinaryFormat::Zebin>(ArrayRef<const uint8_t>::fromAny(zebin.storage.data(), zebin.storage.size())));
240+
241+
auto &buildInfo = pProgram->buildInfos[rootDeviceIndex];
242+
buildInfo.unpackedDeviceBinary.reset(reinterpret_cast<char *>(zebin.storage.data()));
243+
buildInfo.unpackedDeviceBinarySize = zebin.storage.size();
244+
ASSERT_EQ(std::string::npos, buildInfo.kernelMiscInfoPos);
245+
246+
auto &kernelDescriptor = const_cast<KernelDescriptor &>(pKernel->getDescriptor());
247+
kernelDescriptor.explicitArgsExtendedMetadata.clear();
248+
ASSERT_TRUE(kernelDescriptor.explicitArgsExtendedMetadata.empty());
249+
250+
retVal = pKernel->getArgInfo(
251+
0,
252+
CL_KERNEL_ARG_NAME,
253+
0,
254+
nullptr,
255+
0);
256+
257+
EXPECT_EQ(CL_KERNEL_ARG_INFO_NOT_AVAILABLE, retVal);
258+
buildInfo.unpackedDeviceBinary.release();
259+
}
260+
261+
TEST_F(KernelArgInfoTest, givenZebinBinaryWithProperKernelsMiscInfoAndNoExplicitArgsMetadataWhenQueryingArgInfoThenRetrieveItFromKernelsMiscInfo) {
262+
std::string zeInfo = R"===('
263+
kernels:
264+
- name: CopyBuffer
265+
execution_env:
266+
simd_size: 32
267+
payload_arguments:
268+
- arg_type: arg_bypointer
269+
offset: 0
270+
size: 0
271+
arg_index: 0
272+
addrmode: stateful
273+
addrspace: global
274+
access_type: readwrite
275+
- arg_type: arg_bypointer
276+
offset: 32
277+
size: 8
278+
arg_index: 0
279+
addrmode: stateless
280+
addrspace: global
281+
access_type: readwrite
282+
- arg_type: enqueued_local_size
283+
offset: 40
284+
size: 12
285+
kernels_misc_info:
286+
- name: CopyBuffer
287+
args_info:
288+
- index: 0
289+
name: a
290+
address_qualifier: __global
291+
access_qualifier: NONE
292+
type_name: 'int*;8'
293+
type_qualifiers: NONE
294+
)===";
295+
std::vector<uint8_t> storage;
296+
MockElfEncoder<> elfEncoder;
297+
auto &elfHeader = elfEncoder.getElfFileHeader();
298+
elfHeader.type = NEO::Elf::ET_ZEBIN_EXE;
299+
elfHeader.machine = pProgram->getExecutionEnvironment().rootDeviceEnvironments[rootDeviceIndex]->getHardwareInfo()->platform.eProductFamily;
300+
const uint8_t testKernelData[0x10] = {0u};
301+
302+
elfEncoder.appendSection(NEO::Elf::SHT_PROGBITS, NEO::Elf::SectionsNamesZebin::textPrefix.str() + "CopyBuffer", testKernelData);
303+
elfEncoder.appendSection(NEO::Elf::SHT_ZEBIN_ZEINFO, NEO::Elf::SectionsNamesZebin::zeInfo, zeInfo);
304+
storage = elfEncoder.encode();
305+
elfHeader = *reinterpret_cast<NEO::Elf::ElfFileHeader<NEO::Elf::EI_CLASS_64> *>(storage.data());
306+
307+
auto &buildInfo = pProgram->buildInfos[rootDeviceIndex];
308+
309+
//set kernels_misc_info pos manually, as we are not invoking decodeZebin() or processProgramInfo() in this test
310+
ProgramInfo programInfo;
311+
setKernelMiscInfoPosition(zeInfo, programInfo);
312+
buildInfo.kernelMiscInfoPos = programInfo.kernelMiscInfoPos;
313+
buildInfo.unpackedDeviceBinary.reset(reinterpret_cast<char *>(storage.data()));
314+
buildInfo.unpackedDeviceBinarySize = storage.size();
315+
316+
auto &kernelDescriptor = const_cast<KernelDescriptor &>(pKernel->getDescriptor());
317+
kernelDescriptor.explicitArgsExtendedMetadata.clear();
318+
ASSERT_TRUE(kernelDescriptor.explicitArgsExtendedMetadata.empty());
319+
320+
std::array<cl_kernel_arg_info, 5> paramNames = {
321+
CL_KERNEL_ARG_NAME,
322+
CL_KERNEL_ARG_ADDRESS_QUALIFIER,
323+
CL_KERNEL_ARG_ACCESS_QUALIFIER,
324+
CL_KERNEL_ARG_TYPE_NAME,
325+
CL_KERNEL_ARG_TYPE_QUALIFIER,
326+
};
327+
cl_uint argInd = 0;
328+
constexpr size_t maxParamValueSize{0x10};
329+
size_t paramValueSize = 0;
330+
size_t paramValueSizeRet = 0;
331+
332+
for (const auto &paramName : paramNames) {
333+
char paramValue[maxParamValueSize]{0};
334+
335+
retVal = pKernel->getArgInfo(
336+
argInd,
337+
paramName,
338+
paramValueSize,
339+
nullptr,
340+
&paramValueSizeRet);
341+
EXPECT_NE(0u, paramValueSizeRet);
342+
ASSERT_EQ(CL_SUCCESS, retVal);
343+
344+
ASSERT_LT(paramValueSizeRet, maxParamValueSize);
345+
paramValueSize = paramValueSizeRet;
346+
347+
retVal = pKernel->getArgInfo(
348+
argInd,
349+
paramName,
350+
paramValueSize,
351+
paramValue,
352+
nullptr);
353+
ASSERT_EQ(CL_SUCCESS, retVal);
354+
switch (paramName) {
355+
case (CL_KERNEL_ARG_NAME):
356+
EXPECT_EQ(0, strcmp(paramValue, "a"));
357+
break;
358+
case (CL_KERNEL_ARG_ADDRESS_QUALIFIER):
359+
EXPECT_EQ(*(reinterpret_cast<cl_kernel_arg_address_qualifier *>(paramValue)), static_cast<cl_uint>(CL_KERNEL_ARG_ADDRESS_GLOBAL));
360+
break;
361+
case (CL_KERNEL_ARG_ACCESS_QUALIFIER):
362+
EXPECT_EQ(*(reinterpret_cast<cl_kernel_arg_access_qualifier *>(paramValue)), static_cast<cl_uint>(CL_KERNEL_ARG_ACCESS_NONE));
363+
break;
364+
case (CL_KERNEL_ARG_TYPE_NAME):
365+
EXPECT_EQ(0, strcmp(paramValue, "'int*;8'"));
366+
break;
367+
case (CL_KERNEL_ARG_TYPE_QUALIFIER):
368+
EXPECT_EQ(*(reinterpret_cast<cl_kernel_arg_type_qualifier *>(paramValue)), static_cast<cl_ulong>(CL_KERNEL_ARG_TYPE_NONE));
369+
break;
370+
default:
371+
ASSERT_TRUE(false);
372+
break;
373+
}
374+
}
375+
buildInfo.unpackedDeviceBinary.release();
376+
}

Diff for: shared/source/device_binary_format/zebin_decoder.cpp

+22-4
Original file line numberDiff line numberDiff line change
@@ -1609,12 +1609,12 @@ void populateKernelMiscInfo(KernelDescriptor &dst, KernelMiscArgInfos &kernelMis
16091609
}
16101610
}
16111611

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

16201620
NEO::Yaml::YamlParser parser;
@@ -1651,7 +1651,7 @@ NEO::DecodeError decodeAndPopulateKernelMiscInfo(ProgramInfo &dst, ConstStringRe
16511651
return DecodeError::InvalidBinary;
16521652
}
16531653
for (auto &[kName, miscInfos] : kernelArgsMiscInfoVec) {
1654-
for (auto dstKernelInfo : dst.kernelInfos) {
1654+
for (auto dstKernelInfo : kernelInfos) {
16551655
if (dstKernelInfo->kernelDescriptor.kernelMetadata.kernelName == kName) {
16561656
kernelInfo = dstKernelInfo;
16571657
break;
@@ -1810,4 +1810,22 @@ NEO::DecodeError decodeZebin(ProgramInfo &dst, NEO::Elf::Elf<numBits> &elf, std:
18101810
return DecodeError::Success;
18111811
}
18121812

1813+
template <Elf::ELF_IDENTIFIER_CLASS numBits>
1814+
ConstStringRef extractZeInfoMetadataString(const ArrayRef<const uint8_t> zebin, std::string &outErrReason, std::string &outWarning) {
1815+
auto decodedElf = NEO::Elf::decodeElf<numBits>(zebin, outErrReason, outWarning);
1816+
for (const auto &sectionHeader : decodedElf.sectionHeaders) {
1817+
if (sectionHeader.header->type == NEO::Elf::SHT_ZEBIN_ZEINFO) {
1818+
auto zeInfoData = sectionHeader.data;
1819+
return ConstStringRef{reinterpret_cast<const char *>(zeInfoData.begin()), zeInfoData.size()};
1820+
}
1821+
}
1822+
return ConstStringRef{};
1823+
}
1824+
1825+
ConstStringRef extractZeInfoMetadataStringFromZebin(const ArrayRef<const uint8_t> zebin, std::string &outErrReason, std::string &outWarning) {
1826+
return Elf::isElf<Elf::EI_CLASS_32>(zebin)
1827+
? extractZeInfoMetadataString<Elf::EI_CLASS_32>(zebin, outErrReason, outWarning)
1828+
: extractZeInfoMetadataString<Elf::EI_CLASS_64>(zebin, outErrReason, outWarning);
1829+
}
1830+
18131831
} // namespace NEO

Diff for: shared/source/device_binary_format/zebin_decoder.h

+4-1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include "shared/source/device_binary_format/elf/zebin_elf.h"
1313
#include "shared/source/device_binary_format/yaml/yaml_parser.h"
1414
#include "shared/source/kernel/kernel_descriptor.h"
15+
#include "shared/source/program/kernel_info.h"
1516
#include "shared/source/utilities/stackvec.h"
1617

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

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

156-
NEO::DecodeError decodeAndPopulateKernelMiscInfo(ProgramInfo &dst, ConstStringRef metadataString, std::string &outErrReason, std::string &outWarning);
157+
NEO::DecodeError decodeAndPopulateKernelMiscInfo(size_t kernelMiscInfoOffset, std::vector<NEO::KernelInfo *> &kernelInfos, ConstStringRef metadataString, std::string &outErrReason, std::string &outWarning);
158+
159+
ConstStringRef extractZeInfoMetadataStringFromZebin(const ArrayRef<const uint8_t> zebin, std::string &outErrReason, std::string &outWarning);
157160

158161
} // namespace NEO

0 commit comments

Comments
 (0)