Skip to content

Commit 1d51f4b

Browse files
feature: Add driver-experimental API for retrieval of kernel binary program data
Related-To: NEO-11651 Signed-off-by: John Falkowski <[email protected]>
1 parent 9b7ac3a commit 1d51f4b

File tree

10 files changed

+196
-2
lines changed

10 files changed

+196
-2
lines changed

level_zero/api/driver_experimental/public/zex_module.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,12 @@ zexKernelGetBaseAddress(
1818
return L0::Kernel::fromHandle(toInternalType(hKernel))->getBaseAddress(baseAddress);
1919
}
2020

21+
ze_result_t ZE_APICALL
22+
zeIntelKernelGetBinaryExp(
23+
ze_kernel_handle_t hKernel, size_t *pSize, char *pKernelBinary) {
24+
return L0::Kernel::fromHandle(toInternalType(hKernel))->getKernelProgramBinary(pSize, pKernelBinary);
25+
}
26+
2127
} // namespace L0
2228

2329
extern "C" {
@@ -28,4 +34,10 @@ zexKernelGetBaseAddress(
2834
uint64_t *baseAddress) {
2935
return L0::zexKernelGetBaseAddress(hKernel, baseAddress);
3036
}
37+
38+
ZE_APIEXPORT ze_result_t ZE_APICALL
39+
zeIntelKernelGetBinaryExp(
40+
ze_kernel_handle_t hKernel, size_t *pSize, char *pKernelBinary) {
41+
return L0::zeIntelKernelGetBinaryExp(hKernel, pSize, pKernelBinary);
42+
}
3143
}

level_zero/api/driver_experimental/public/zex_module.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,11 @@ zexKernelGetBaseAddress(
1818
ze_kernel_handle_t hKernel,
1919
uint64_t *baseAddress);
2020

21-
}
21+
ze_result_t ZE_APICALL
22+
zeIntelKernelGetBinaryExp(
23+
ze_kernel_handle_t hKernel, size_t *pSize, char *pKernelBinary);
24+
25+
} // namespace L0
2226

2327
///////////////////////////////////////////////////////////////////////////////
2428
/// @brief General Register File descriptor.

level_zero/core/source/driver/driver_handle_imp_helper.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,5 +38,5 @@ const std::vector<std::pair<std::string, uint32_t>> DriverHandleImp::extensionsS
3838
{ZE_INTEL_COMMAND_LIST_MEMORY_SYNC, ZE_INTEL_COMMAND_LIST_MEMORY_SYNC_EXP_VERSION_CURRENT},
3939
{ZEX_INTEL_EVENT_SYNC_MODE_EXP_NAME, ZEX_INTEL_EVENT_SYNC_MODE_EXP_VERSION_CURRENT},
4040
{ZE_INTEL_GET_DRIVER_VERSION_STRING_EXP_NAME, ZE_INTEL_GET_DRIVER_VERSION_STRING_EXP_VERSION_CURRENT},
41-
};
41+
{ZE_INTEL_KERNEL_GET_PROGRAM_BINARY_EXP_NAME, ZE_INTEL_KERNEL_GET_PROGRAM_BINARY_EXP_VERSION_CURRENT}};
4242
} // namespace L0

level_zero/core/source/driver/extension_function_address.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ void *ExtensionFunctionAddressHelper::getExtensionFunctionAddress(const std::str
3030
RETURN_FUNC_PTR_IF_EXIST(zexDriverGetHostPointerBaseAddress);
3131

3232
RETURN_FUNC_PTR_IF_EXIST(zexKernelGetBaseAddress);
33+
RETURN_FUNC_PTR_IF_EXIST(zeIntelKernelGetBinaryExp);
3334

3435
RETURN_FUNC_PTR_IF_EXIST(zexMemGetIpcHandles);
3536
RETURN_FUNC_PTR_IF_EXIST(zexMemOpenIpcHandles);

level_zero/core/source/kernel/kernel.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ struct Kernel : _ze_kernel_handle_t, virtual NEO::DispatchKernelEncoderI {
123123

124124
virtual ze_result_t destroy() = 0;
125125
virtual ze_result_t getBaseAddress(uint64_t *baseAddress) = 0;
126+
virtual ze_result_t getKernelProgramBinary(size_t *kernelSize, char *pKernelBinary) = 0;
126127
virtual ze_result_t setIndirectAccess(ze_kernel_indirect_access_flags_t flags) = 0;
127128
virtual ze_result_t getIndirectAccess(ze_kernel_indirect_access_flags_t *flags) = 0;
128129
virtual ze_result_t getSourceAttributes(uint32_t *pSize, char **pString) = 0;

level_zero/core/source/kernel/kernel_imp.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,18 @@ KernelImp::~KernelImp() {
276276
dynamicStateHeapData.reset();
277277
}
278278

279+
ze_result_t KernelImp::getKernelProgramBinary(size_t *kernelSize, char *pKernelBinary) {
280+
size_t kSize = static_cast<size_t>(this->kernelImmData->getKernelInfo()->heapInfo.kernelHeapSize);
281+
if (nullptr == pKernelBinary) {
282+
*kernelSize = kSize;
283+
return ZE_RESULT_SUCCESS;
284+
}
285+
*kernelSize = std::min(*kernelSize, kSize);
286+
memcpy_s(pKernelBinary, *kernelSize, this->kernelImmData->getKernelInfo()->heapInfo.pKernelHeap, *kernelSize);
287+
288+
return ZE_RESULT_SUCCESS;
289+
}
290+
279291
ze_result_t KernelImp::setArgumentValue(uint32_t argIndex, size_t argSize,
280292
const void *pArgValue) {
281293
if (argIndex >= kernelArgHandlers.size()) {

level_zero/core/source/kernel/kernel_imp.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ struct KernelImp : Kernel {
4949
}
5050

5151
ze_result_t getBaseAddress(uint64_t *baseAddress) override;
52+
ze_result_t getKernelProgramBinary(size_t *kernelSize, char *pKernelBinary) override;
5253
ze_result_t setIndirectAccess(ze_kernel_indirect_access_flags_t flags) override;
5354
ze_result_t getIndirectAccess(ze_kernel_indirect_access_flags_t *flags) override;
5455
ze_result_t getSourceAttributes(uint32_t *pSize, char **pString) override;

level_zero/core/test/unit_tests/sources/kernel/test_kernel.cpp

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3413,6 +3413,77 @@ TEST_F(KernelGlobalWorkOffsetTests, whenSettingGlobalOffsetThenCrossThreadDataIs
34133413
EXPECT_EQ(*(dst.begin() + desc.payloadMappings.dispatchTraits.globalWorkOffset[2]), globalOffsetz);
34143414
}
34153415

3416+
class KernelProgramBinaryTests : public ModuleFixture, public ::testing::Test {
3417+
public:
3418+
void SetUp() override {
3419+
ModuleFixture::setUp();
3420+
3421+
ze_kernel_desc_t kernelDesc = {};
3422+
kernelDesc.pKernelName = kernelName.c_str();
3423+
3424+
ze_result_t res = module->createKernel(&kernelDesc, &kernelHandle);
3425+
EXPECT_EQ(ZE_RESULT_SUCCESS, res);
3426+
3427+
kernel = L0::Kernel::fromHandle(kernelHandle);
3428+
}
3429+
3430+
void TearDown() override {
3431+
Kernel::fromHandle(kernelHandle)->destroy();
3432+
ModuleFixture::tearDown();
3433+
}
3434+
3435+
ze_kernel_handle_t kernelHandle;
3436+
L0::Kernel *kernel = nullptr;
3437+
};
3438+
3439+
TEST_F(KernelProgramBinaryTests, givenCallToGetKernelProgramBinaryThenCorrectSizeAndDataReturned) {
3440+
3441+
size_t kernelBinarySize = 0;
3442+
char *kernelBinaryRetrieved = nullptr;
3443+
EXPECT_EQ(ZE_RESULT_SUCCESS, kernel->getKernelProgramBinary(&kernelBinarySize, kernelBinaryRetrieved));
3444+
EXPECT_GT(kernelBinarySize, 0u);
3445+
kernelBinaryRetrieved = new char[kernelBinarySize];
3446+
EXPECT_EQ(ZE_RESULT_SUCCESS, kernel->getKernelProgramBinary(&kernelBinarySize, kernelBinaryRetrieved));
3447+
3448+
auto &kernelImmutableData = this->module->kernelImmDatas.front();
3449+
EXPECT_EQ(kernelBinarySize, kernelImmutableData->getKernelInfo()->heapInfo.kernelHeapSize);
3450+
const char *heapPtr = reinterpret_cast<const char *>(kernelImmutableData->getKernelInfo()->heapInfo.pKernelHeap);
3451+
EXPECT_EQ(0, memcmp(kernelBinaryRetrieved, heapPtr, kernelBinarySize));
3452+
delete[] kernelBinaryRetrieved;
3453+
}
3454+
3455+
TEST_F(KernelProgramBinaryTests, givenCallToGetKernelProgramBinaryWithSmallSizeThenSmallSizeReturned) {
3456+
size_t kernelBinarySize = 0;
3457+
char *kernelBinaryRetrieved = nullptr;
3458+
EXPECT_EQ(ZE_RESULT_SUCCESS, kernel->getKernelProgramBinary(&kernelBinarySize, kernelBinaryRetrieved));
3459+
kernelBinaryRetrieved = new char[kernelBinarySize];
3460+
size_t kernelBinarySize2 = kernelBinarySize / 2;
3461+
EXPECT_EQ(ZE_RESULT_SUCCESS, kernel->getKernelProgramBinary(&kernelBinarySize2, kernelBinaryRetrieved));
3462+
EXPECT_EQ(kernelBinarySize2, (kernelBinarySize / 2));
3463+
3464+
auto &kernelImmutableData = this->module->kernelImmDatas.front();
3465+
EXPECT_EQ(kernelBinarySize, kernelImmutableData->getKernelInfo()->heapInfo.kernelHeapSize);
3466+
const char *heapPtr = reinterpret_cast<const char *>(kernelImmutableData->getKernelInfo()->heapInfo.pKernelHeap);
3467+
EXPECT_EQ(0, memcmp(kernelBinaryRetrieved, heapPtr, kernelBinarySize2));
3468+
delete[] kernelBinaryRetrieved;
3469+
}
3470+
3471+
TEST_F(KernelProgramBinaryTests, givenCallToGetKernelProgramBinaryWithLargeSizeThenCorrectSizeReturned) {
3472+
size_t kernelBinarySize = 0;
3473+
char *kernelBinaryRetrieved = nullptr;
3474+
EXPECT_EQ(ZE_RESULT_SUCCESS, kernel->getKernelProgramBinary(&kernelBinarySize, kernelBinaryRetrieved));
3475+
kernelBinaryRetrieved = new char[kernelBinarySize];
3476+
size_t kernelBinarySize2 = kernelBinarySize * 2;
3477+
EXPECT_EQ(ZE_RESULT_SUCCESS, kernel->getKernelProgramBinary(&kernelBinarySize2, kernelBinaryRetrieved));
3478+
EXPECT_EQ(kernelBinarySize2, kernelBinarySize);
3479+
3480+
auto &kernelImmutableData = this->module->kernelImmDatas.front();
3481+
EXPECT_EQ(kernelBinarySize2, kernelImmutableData->getKernelInfo()->heapInfo.kernelHeapSize);
3482+
const char *heapPtr = reinterpret_cast<const char *>(kernelImmutableData->getKernelInfo()->heapInfo.pKernelHeap);
3483+
EXPECT_EQ(0, memcmp(kernelBinaryRetrieved, heapPtr, kernelBinarySize2));
3484+
delete[] kernelBinaryRetrieved;
3485+
}
3486+
34163487
using KernelWorkDimTests = Test<ModuleImmutableDataFixture>;
34173488

34183489
TEST_F(KernelWorkDimTests, givenGroupCountsWhenPatchingWorkDimThenCrossThreadDataIsPatched) {
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
<!---
2+
3+
Copyright (C) 2024 Intel Corporation
4+
5+
SPDX-License-Identifier: MIT
6+
7+
-->
8+
9+
# Get Driver Version String
10+
11+
* [Overview](#Overview)
12+
* [Definitions](#Definitions)
13+
14+
# Overview
15+
16+
A new extension API 'zeIntelKernelGetBinaryExp' is created to retrieve both the size of the kernel binary program data, and the data itself. It can first be called to obtain the size of the kernel binary program data. The application then allocates memory accordingly and in the second call retrieves the kernel binary program data.
17+
18+
`zeIntelKernelGetBinaryExp` returns Intel Graphics Assembly (GEN ISA) format binary program data for kernel handle. The binary program data may be directly disassembled with iga64 offline tool.
19+
20+
# Definitions
21+
22+
```cpp
23+
#define ZE_INTEL_KERNEL_GET_PROGRAM_BINARY_EXP_NAME "ZE_intel_experimental_kernel_get_program_binary"
24+
```
25+
26+
## Interfaces
27+
28+
```cpp
29+
/// @brief Get Kernel Program Binary
30+
///
31+
/// @details
32+
/// - A valid kernel handle must be created with zeKernelCreate.
33+
/// - Returns Intel Graphics Assembly (GEN ISA) format binary program data for kernel handle.
34+
/// - The application may call this function from simultaneous threads.
35+
/// - The implementation of this function should be lock-free.
36+
/// @returns
37+
/// - ::ZE_RESULT_SUCCESS
38+
ze_result_t ZE_APICALL
39+
zeIntelKernelGetBinaryExp(
40+
ze_kernel_handle_t hKernel, ///< [in] Kernel handle
41+
size_t *pSize, ///< [in, out] pointer to variable with size of GEN ISA binary
42+
char *pKernelBinary ///< [in,out] pointer to storage area for GEN ISA binary function
43+
);
44+
```
45+
46+
## Programming example
47+
48+
```cpp
49+
#include <fstream>
50+
51+
//kernel = valid kernel handle
52+
size_t kBinarySize = 0;
53+
zeKernelGetBinaryExp(kernel, &kBinarySize, nullptr);
54+
char *progArray;
55+
program_array = new char[kBinarySize];
56+
zeKernelGetBinaryExp(kernel, &kBinarySize, progArray);
57+
const std::string file_path = "program_binary.bin";
58+
std::ofstream stream(file_path, std::ios::out | std::ios::binary);
59+
stream.write(reinterpret_cast<const char *>(progArray), kBinarySize);
60+
stream.close();
61+
```

level_zero/include/ze_intel_gpu.h

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,37 @@ zeIntelGetDriverVersionString(
235235
size_t *pVersionSize); ///< [in,out] pointer to the size of the driver version string.
236236
///< if size is zero, then the size of the version string is returned.
237237

238+
/// @brief Get Kernel Program Binary
239+
///
240+
/// @details
241+
/// - A valid kernel handle must be created with zeKernelCreate.
242+
/// - Returns Intel Graphics Assembly (GEN ISA) format binary program data for kernel handle.
243+
/// - The application may call this function from simultaneous threads.
244+
/// - The implementation of this function should be lock-free.
245+
/// @returns
246+
/// - ::ZE_RESULT_SUCCESS
247+
248+
#ifndef ZE_INTEL_KERNEL_GET_PROGRAM_BINARY_EXP_NAME
249+
/// @brief Get Kernel Program Binary experimental name
250+
#define ZE_INTEL_KERNEL_GET_PROGRAM_BINARY_EXP_NAME "ZE_intel_experimental_kernel_get_program_binary"
251+
#endif // ZE_INTEL_KERNEL_GET_PROGRAM_BINARY_EXP_NAME
252+
253+
///////////////////////////////////////////////////////////////////////////////
254+
/// @brief Intel Kernel Get Binary Extension Version(s)
255+
typedef enum _ze_intel_kernel_get_binary_exp_version_t {
256+
ZE_INTEL_KERNEL_GET_PROGRAM_BINARY_EXP_VERSION_1_0 = ZE_MAKE_VERSION(1, 0), ///< version 1.0
257+
ZE_INTEL_KERNEL_GET_PROGRAM_BINARY_EXP_VERSION_CURRENT = ZE_MAKE_VERSION(1, 0), ///< latest known version
258+
ZE_INTEL_KERNEL_GET_PROGRAM_BINARY_EXP_VERSION_FORCE_UINT32 = 0x7fffffff
259+
260+
} ze_intel_kernel_get_binary_exp_version_t;
261+
262+
ze_result_t ZE_APICALL
263+
zeIntelKernelGetBinaryExp(
264+
ze_kernel_handle_t hKernel, ///< [in] Kernel handle
265+
size_t *pSize, ///< [in, out] pointer to variable with size of GEN ISA binary
266+
char *pKernelBinary ///< [in,out] pointer to storage area for GEN ISA binary function
267+
);
268+
238269
#if defined(__cplusplus)
239270
} // extern "C"
240271
#endif

0 commit comments

Comments
 (0)