Skip to content

Commit fc22420

Browse files
Create debug zebin in OCL
This commit adds debug zebin creation in OCL. - Added returning debug zebin in build/linking paths in OCL if corresponding device binary format was detected. - Refactored getZebinSegments() method - added common ctor for both L0/OCL paths Signed-off-by: Kacper Nowak <[email protected]>
1 parent 59683ec commit fc22420

File tree

11 files changed

+275
-32
lines changed

11 files changed

+275
-32
lines changed

level_zero/core/source/module/module_imp.cpp

Lines changed: 6 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -440,31 +440,12 @@ ModuleImp::~ModuleImp() {
440440
}
441441

442442
NEO::Debug::Segments ModuleImp::getZebinSegments() {
443-
NEO::Debug::Segments segments;
444-
445-
auto varBuffer = translationUnit->globalVarBuffer;
446-
if (varBuffer) {
447-
segments.varData = {varBuffer->getGpuAddressToPatch(), {reinterpret_cast<uint8_t *>(varBuffer->getUnderlyingBuffer()), varBuffer->getUnderlyingBufferSize()}};
448-
}
449-
450-
auto constBuffer = translationUnit->globalConstBuffer;
451-
if (constBuffer) {
452-
segments.constData = {constBuffer->getGpuAddressToPatch(), {reinterpret_cast<uint8_t *>(constBuffer->getUnderlyingBuffer()), constBuffer->getUnderlyingBufferSize()}};
453-
}
454-
455-
auto stringBuffer = translationUnit->programInfo.globalStrings;
456-
if (stringBuffer.initData) {
457-
segments.stringData = {reinterpret_cast<uintptr_t>(stringBuffer.initData),
458-
{reinterpret_cast<const uint8_t *>(stringBuffer.initData), stringBuffer.size}};
459-
}
460-
461-
for (auto &kernImmData : this->kernelImmDatas) {
462-
const auto &isa = kernImmData->getIsaGraphicsAllocation();
463-
NEO::Debug::Segments::Segment kernelSegment = {isa->getGpuAddressToPatch(), {reinterpret_cast<uint8_t *>(isa->getUnderlyingBuffer()), isa->getUnderlyingBufferSize()}};
464-
segments.nameToSegMap.insert(std::pair(kernImmData->getDescriptor().kernelMetadata.kernelName, kernelSegment));
465-
}
466-
467-
return segments;
443+
std::vector<std::pair<std::string_view, NEO::GraphicsAllocation *>> kernels;
444+
for (const auto &kernelImmData : kernelImmDatas)
445+
kernels.push_back({kernelImmData->getDescriptor().kernelMetadata.kernelName, kernelImmData->getIsaGraphicsAllocation()});
446+
ArrayRef<const uint8_t> strings = {reinterpret_cast<const uint8_t *>(translationUnit->programInfo.globalStrings.initData),
447+
translationUnit->programInfo.globalStrings.size};
448+
return NEO::Debug::Segments(translationUnit->globalVarBuffer, translationUnit->globalConstBuffer, strings, kernels);
468449
}
469450

470451
bool ModuleImp::initialize(const ze_module_desc_t *desc, NEO::Device *neoDevice) {

opencl/source/program/build.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ cl_int Program::build(
186186
if (BuildPhase::DebugDataNotification == phaseReached[rootDeviceIndex]) {
187187
continue;
188188
}
189-
processDebugData(rootDeviceIndex);
189+
createDebugData(clDevice->getRootDeviceIndex());
190190
if (clDevice->getSourceLevelDebugger()) {
191191
for (auto kernelInfo : buildInfos[rootDeviceIndex].kernelInfoArray) {
192192
clDevice->getSourceLevelDebugger()->notifyKernelDebugData(&kernelInfo->debugData,

opencl/source/program/link.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ cl_int Program::link(
170170
if (kernelDebugDataNotified[rootDeviceIndex]) {
171171
continue;
172172
}
173-
processDebugData(rootDeviceIndex);
173+
createDebugData(rootDeviceIndex);
174174
for (auto kernelInfo : buildInfos[rootDeviceIndex].kernelInfoArray) {
175175
device->getSourceLevelDebugger()->notifyKernelDebugData(&kernelInfo->debugData,
176176
kernelInfo->kernelDescriptor.kernelMetadata.kernelName,

opencl/source/program/process_device_binary.cpp

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (C) 2020-2021 Intel Corporation
2+
* Copyright (C) 2020-2022 Intel Corporation
33
*
44
* SPDX-License-Identifier: MIT
55
*
@@ -61,6 +61,7 @@ cl_int Program::linkBinary(Device *pDevice, const void *constantsInitData, const
6161
}
6262
auto rootDeviceIndex = pDevice->getRootDeviceIndex();
6363
auto &kernelInfoArray = buildInfos[rootDeviceIndex].kernelInfoArray;
64+
buildInfos[rootDeviceIndex].constStringSectionData = stringsInfo;
6465
Linker linker(*linkerInput);
6566
Linker::SegmentInfo globals;
6667
Linker::SegmentInfo constants;
@@ -276,4 +277,36 @@ void Program::processDebugData(uint32_t rootDeviceIndex) {
276277
}
277278
}
278279

280+
Debug::Segments Program::getZebinSegments(uint32_t rootDeviceIndex) {
281+
ArrayRef<const uint8_t> strings = {reinterpret_cast<const uint8_t *>(buildInfos[rootDeviceIndex].constStringSectionData.initData),
282+
buildInfos[rootDeviceIndex].constStringSectionData.size};
283+
std::vector<std::pair<std::string_view, NEO::GraphicsAllocation *>> kernels;
284+
for (const auto &kernelInfo : buildInfos[rootDeviceIndex].kernelInfoArray)
285+
kernels.push_back({kernelInfo->kernelDescriptor.kernelMetadata.kernelName, kernelInfo->getGraphicsAllocation()});
286+
287+
return Debug::Segments(getGlobalSurface(rootDeviceIndex), getConstantSurface(rootDeviceIndex), strings, kernels);
288+
}
289+
290+
void Program::createDebugZebin(uint32_t rootDeviceIndex) {
291+
if (debugDataSize != 0) {
292+
return;
293+
}
294+
auto refBin = ArrayRef<const uint8_t>(reinterpret_cast<const uint8_t *>(buildInfos[rootDeviceIndex].unpackedDeviceBinary.get()), buildInfos[rootDeviceIndex].unpackedDeviceBinarySize);
295+
auto segments = getZebinSegments(rootDeviceIndex);
296+
auto debugZebin = Debug::createDebugZebin(refBin, segments);
297+
298+
debugDataSize = debugZebin.size();
299+
debugData.reset(new char[debugDataSize]);
300+
memcpy_s(debugData.get(), debugDataSize,
301+
debugZebin.data(), debugZebin.size());
302+
}
303+
304+
void Program::createDebugData(uint32_t rootDeviceIndex) {
305+
auto refBin = ArrayRef<const uint8_t>(reinterpret_cast<const uint8_t *>(buildInfos[rootDeviceIndex].unpackedDeviceBinary.get()), buildInfos[rootDeviceIndex].unpackedDeviceBinarySize);
306+
if (isDeviceBinaryFormat<DeviceBinaryFormat::Zebin>(refBin)) {
307+
createDebugZebin(rootDeviceIndex);
308+
} else {
309+
processDebugData(rootDeviceIndex);
310+
}
311+
}
279312
} // namespace NEO

opencl/source/program/program.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#pragma once
99
#include "shared/source/compiler_interface/compiler_interface.h"
1010
#include "shared/source/compiler_interface/linker.h"
11+
#include "shared/source/device_binary_format/debug_zebin.h"
1112
#include "shared/source/device_binary_format/elf/elf_encoder.h"
1213
#include "shared/source/helpers/non_copyable_or_moveable.h"
1314
#include "shared/source/program/program_info.h"
@@ -173,7 +174,7 @@ class Program : public BaseObject<_cl_program> {
173174

174175
cl_int getSource(std::string &binary) const;
175176

176-
void processDebugData(uint32_t rootDeviceIndex);
177+
MOCKABLE_VIRTUAL void processDebugData(uint32_t rootDeviceIndex);
177178

178179
void updateBuildLog(uint32_t rootDeviceIndex, const char *pErrorString, const size_t errorStringSize);
179180

@@ -282,6 +283,10 @@ class Program : public BaseObject<_cl_program> {
282283
this->context = pContext;
283284
}
284285

286+
void createDebugData(uint32_t rootDeviceIndex);
287+
MOCKABLE_VIRTUAL void createDebugZebin(uint32_t rootDeviceIndex);
288+
Debug::Segments getZebinSegments(uint32_t rootDeviceIndex);
289+
285290
protected:
286291
MOCKABLE_VIRTUAL cl_int createProgramFromBinary(const void *pBinary, size_t binarySize, ClDevice &clDevice);
287292

@@ -350,6 +355,7 @@ class Program : public BaseObject<_cl_program> {
350355

351356
std::unique_ptr<char[]> packedDeviceBinary;
352357
size_t packedDeviceBinarySize = 0U;
358+
ProgramInfo::GlobalSurfaceInfo constStringSectionData;
353359
};
354360

355361
std::vector<BuildInfo> buildInfos;

opencl/test/unit_test/program/CMakeLists.txt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#
2-
# Copyright (C) 2018-2021 Intel Corporation
2+
# Copyright (C) 2018-2022 Intel Corporation
33
#
44
# SPDX-License-Identifier: MIT
55
#
@@ -25,6 +25,9 @@ set(IGDRCL_SRCS_tests_program
2525
${CMAKE_CURRENT_SOURCE_DIR}/program_with_block_kernels_tests.cpp
2626
${CMAKE_CURRENT_SOURCE_DIR}/program_with_kernel_debug_tests.cpp
2727
${CMAKE_CURRENT_SOURCE_DIR}/program_with_source.h
28+
${CMAKE_CURRENT_SOURCE_DIR}/program_with_zebin.h
29+
${CMAKE_CURRENT_SOURCE_DIR}/program_with_zebin.cpp
30+
${CMAKE_CURRENT_SOURCE_DIR}/program_with_zebin_tests.cpp
2831
)
2932

3033
get_property(NEO_CORE_SRCS_tests_program GLOBAL PROPERTY NEO_CORE_SRCS_tests_program)
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/*
2+
* Copyright (C) 2022 Intel Corporation
3+
*
4+
* SPDX-License-Identifier: MIT
5+
*
6+
*/
7+
8+
#include "opencl/test/unit_test/program/program_with_zebin.h"
9+
10+
#include "shared/test/unit_test/device_binary_format/zebin_tests.h"
11+
12+
#include "opencl/test/unit_test/mocks/mock_buffer.h"
13+
14+
using namespace NEO;
15+
16+
void ProgramWithZebinFixture::SetUp() {
17+
ProgramTests::SetUp();
18+
program = std::make_unique<MockProgram>(toClDeviceVector(*pClDevice));
19+
}
20+
21+
void ProgramWithZebinFixture::TearDown() {
22+
program->setGlobalSurface(nullptr);
23+
program->setConstantSurface(nullptr);
24+
program->getKernelInfoArray(rootDeviceIndex).clear();
25+
ProgramTests::TearDown();
26+
}
27+
28+
void ProgramWithZebinFixture::addEmptyZebin(NEO::MockProgram *program) {
29+
auto zebin = ZebinTestData::ValidEmptyProgram();
30+
31+
program->buildInfos[rootDeviceIndex].unpackedDeviceBinarySize = zebin.storage.size();
32+
program->buildInfos[rootDeviceIndex].unpackedDeviceBinary.reset(new char[zebin.storage.size()]);
33+
memcpy_s(program->buildInfos[rootDeviceIndex].unpackedDeviceBinary.get(), program->buildInfos[rootDeviceIndex].unpackedDeviceBinarySize,
34+
zebin.storage.data(), zebin.storage.size());
35+
}
36+
37+
void ProgramWithZebinFixture::populateProgramWithSegments(NEO::MockProgram *program) {
38+
kernelInfo = std::make_unique<KernelInfo>();
39+
kernelInfo->kernelDescriptor.kernelMetadata.kernelName = kernelName;
40+
mockAlloc = std::make_unique<MockGraphicsAllocation>();
41+
kernelInfo->kernelAllocation = mockAlloc.get();
42+
43+
program->addKernelInfo(kernelInfo.get(), rootDeviceIndex);
44+
45+
globalSurface = std::make_unique<MockBuffer>();
46+
constantSurface = std::make_unique<MockBuffer>();
47+
program->setGlobalSurface(&globalSurface->mockGfxAllocation);
48+
program->setConstantSurface(&constantSurface->mockGfxAllocation);
49+
50+
program->buildInfos[rootDeviceIndex].constStringSectionData.initData = &strings;
51+
program->buildInfos[rootDeviceIndex].constStringSectionData.size = sizeof(strings);
52+
}
53+
54+
void ProgramWithDebugDataCreationFixture::SetUp() {
55+
ProgramWithZebinFixture::SetUp();
56+
programWithDebugDataCreation = std::make_unique<MockProgramWithDebugDataCreation>(toClDeviceVector(*pClDevice));
57+
}
58+
59+
void ProgramWithDebugDataCreationFixture::TearDown() {
60+
ProgramWithZebinFixture::TearDown();
61+
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/*
2+
* Copyright (C) 2022 Intel Corporation
3+
*
4+
* SPDX-License-Identifier: MIT
5+
*
6+
*/
7+
8+
#pragma once
9+
#include "opencl/test/unit_test/mocks/mock_program.h"
10+
#include "opencl/test/unit_test/program/program_tests.h"
11+
12+
using namespace NEO;
13+
14+
class MockBuffer;
15+
class ProgramWithZebinFixture : public ProgramTests {
16+
public:
17+
std::unique_ptr<MockProgram> program;
18+
std::unique_ptr<KernelInfo> kernelInfo;
19+
std::unique_ptr<MockGraphicsAllocation> mockAlloc;
20+
std::unique_ptr<MockBuffer> globalSurface;
21+
std::unique_ptr<MockBuffer> constantSurface;
22+
const char strings[12] = "Hello olleH";
23+
const char kernelName[8] = "kernel1";
24+
void SetUp() override;
25+
void TearDown() override;
26+
void addEmptyZebin(MockProgram *program);
27+
void populateProgramWithSegments(MockProgram *program);
28+
~ProgramWithZebinFixture() = default;
29+
};
30+
31+
class ProgramWithDebugDataCreationFixture : public ProgramWithZebinFixture {
32+
33+
class MockProgramWithDebugDataCreation : public MockProgram {
34+
public:
35+
using Program::createDebugData;
36+
MockProgramWithDebugDataCreation(const ClDeviceVector &deviceVector) : MockProgram(deviceVector) {
37+
}
38+
~MockProgramWithDebugDataCreation() {
39+
}
40+
bool wasProcessDebugDataCalled = false;
41+
void processDebugData(uint32_t rootDeviceIndex) override {
42+
wasProcessDebugDataCalled = true;
43+
}
44+
bool wasCreateDebugZebinCalled = false;
45+
void createDebugZebin(uint32_t rootDeviceIndex) override {
46+
wasCreateDebugZebinCalled = true;
47+
}
48+
};
49+
50+
public:
51+
std::unique_ptr<MockProgramWithDebugDataCreation> programWithDebugDataCreation;
52+
void SetUp() override;
53+
void TearDown() override;
54+
};
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
/*
2+
* Copyright (C) 2022 Intel Corporation
3+
*
4+
* SPDX-License-Identifier: MIT
5+
*
6+
*/
7+
8+
#include "shared/test/common/test_macros/test.h"
9+
10+
#include "opencl/test/unit_test/mocks/mock_buffer.h"
11+
#include "opencl/test/unit_test/program/program_with_zebin.h"
12+
13+
#include <memory>
14+
using namespace NEO;
15+
16+
TEST_F(ProgramWithZebinFixture, givenNoZebinThenSegmentsAreEmpty) {
17+
auto segments = program->getZebinSegments(pClDevice->getRootDeviceIndex());
18+
19+
EXPECT_EQ(std::numeric_limits<uintptr_t>::max(), segments.constData.address);
20+
EXPECT_TRUE(segments.constData.data.empty());
21+
22+
EXPECT_EQ(std::numeric_limits<uintptr_t>::max(), segments.varData.address);
23+
EXPECT_TRUE(segments.varData.data.empty());
24+
25+
EXPECT_EQ(std::numeric_limits<uintptr_t>::max(), segments.stringData.address);
26+
EXPECT_TRUE(segments.stringData.data.empty());
27+
28+
EXPECT_TRUE(segments.nameToSegMap.empty());
29+
}
30+
31+
TEST_F(ProgramWithZebinFixture, givenZebinSegmentsThenSegmentsArePopulated) {
32+
populateProgramWithSegments(program.get());
33+
auto segments = program->getZebinSegments(rootDeviceIndex);
34+
35+
auto checkGPUSeg = [](NEO::GraphicsAllocation *alloc, NEO::Debug::Segments::Segment segment) {
36+
EXPECT_EQ(static_cast<uintptr_t>(alloc->getGpuAddressToPatch()), segment.address);
37+
EXPECT_EQ(reinterpret_cast<uint8_t *>(alloc->getUnderlyingBuffer()), segment.data.begin());
38+
EXPECT_EQ(static_cast<size_t>(alloc->getUnderlyingBufferSize()), segment.data.size());
39+
};
40+
checkGPUSeg(program->buildInfos[rootDeviceIndex].constantSurface, segments.constData);
41+
checkGPUSeg(program->buildInfos[rootDeviceIndex].globalSurface, segments.varData);
42+
checkGPUSeg(program->getKernelInfoArray(rootDeviceIndex)[0]->getGraphicsAllocation(), segments.nameToSegMap["kernel1"]);
43+
44+
EXPECT_EQ(reinterpret_cast<uintptr_t>(program->buildInfos[rootDeviceIndex].constStringSectionData.initData), segments.stringData.address);
45+
EXPECT_EQ(reinterpret_cast<const uint8_t *>(program->buildInfos[rootDeviceIndex].constStringSectionData.initData), segments.stringData.data.begin());
46+
EXPECT_EQ(program->buildInfos[rootDeviceIndex].constStringSectionData.size, segments.stringData.data.size());
47+
}
48+
49+
TEST_F(ProgramWithZebinFixture, givenNonEmptyDebugDataThenDebugZebinIsNotCreated) {
50+
addEmptyZebin(program.get());
51+
populateProgramWithSegments(program.get());
52+
program->debugDataSize = 8u;
53+
program->debugData.reset(nullptr);
54+
program->createDebugZebin(rootDeviceIndex);
55+
EXPECT_EQ(nullptr, program->debugData.get());
56+
}
57+
58+
TEST_F(ProgramWithZebinFixture, givenEmptyDebugDataThenDebugZebinIsCreatedAndStoredInDebugData) {
59+
addEmptyZebin(program.get());
60+
populateProgramWithSegments(program.get());
61+
62+
program->debugDataSize = 0u;
63+
program->debugData.reset(nullptr);
64+
program->createDebugZebin(rootDeviceIndex);
65+
EXPECT_NE(nullptr, program->debugData.get());
66+
}
67+
68+
TEST_F(ProgramWithDebugDataCreationFixture, givenZebinaryFormatInCreateDebugDataThenCreateDebugZebinIsCalled) {
69+
addEmptyZebin(programWithDebugDataCreation.get());
70+
programWithDebugDataCreation->createDebugData(rootDeviceIndex);
71+
EXPECT_TRUE(programWithDebugDataCreation->wasCreateDebugZebinCalled);
72+
EXPECT_FALSE(programWithDebugDataCreation->wasProcessDebugDataCalled);
73+
}
74+
75+
TEST_F(ProgramWithDebugDataCreationFixture, givenNonZebinaryFormatInCreateDebugDataThenProcessDebugDataIsCalled) {
76+
size_t fakeBinarySize = 8u;
77+
programWithDebugDataCreation->buildInfos[rootDeviceIndex].unpackedDeviceBinarySize = fakeBinarySize;
78+
programWithDebugDataCreation->buildInfos[rootDeviceIndex].unpackedDeviceBinary.reset(new char[fakeBinarySize]);
79+
programWithDebugDataCreation->createDebugData(rootDeviceIndex);
80+
EXPECT_FALSE(programWithDebugDataCreation->wasCreateDebugZebinCalled);
81+
EXPECT_TRUE(programWithDebugDataCreation->wasProcessDebugDataCalled);
82+
}

0 commit comments

Comments
 (0)