mirror of
https://github.com/intel/compute-runtime.git
synced 2025-09-15 13:01:45 +08:00
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 <kacper.nowak@intel.com>
This commit is contained in:

committed by
Compute-Runtime-Automation

parent
59683ec491
commit
fc224202d6
@ -186,7 +186,7 @@ cl_int Program::build(
|
||||
if (BuildPhase::DebugDataNotification == phaseReached[rootDeviceIndex]) {
|
||||
continue;
|
||||
}
|
||||
processDebugData(rootDeviceIndex);
|
||||
createDebugData(clDevice->getRootDeviceIndex());
|
||||
if (clDevice->getSourceLevelDebugger()) {
|
||||
for (auto kernelInfo : buildInfos[rootDeviceIndex].kernelInfoArray) {
|
||||
clDevice->getSourceLevelDebugger()->notifyKernelDebugData(&kernelInfo->debugData,
|
||||
|
@ -170,7 +170,7 @@ cl_int Program::link(
|
||||
if (kernelDebugDataNotified[rootDeviceIndex]) {
|
||||
continue;
|
||||
}
|
||||
processDebugData(rootDeviceIndex);
|
||||
createDebugData(rootDeviceIndex);
|
||||
for (auto kernelInfo : buildInfos[rootDeviceIndex].kernelInfoArray) {
|
||||
device->getSourceLevelDebugger()->notifyKernelDebugData(&kernelInfo->debugData,
|
||||
kernelInfo->kernelDescriptor.kernelMetadata.kernelName,
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2020-2021 Intel Corporation
|
||||
* Copyright (C) 2020-2022 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
@ -61,6 +61,7 @@ cl_int Program::linkBinary(Device *pDevice, const void *constantsInitData, const
|
||||
}
|
||||
auto rootDeviceIndex = pDevice->getRootDeviceIndex();
|
||||
auto &kernelInfoArray = buildInfos[rootDeviceIndex].kernelInfoArray;
|
||||
buildInfos[rootDeviceIndex].constStringSectionData = stringsInfo;
|
||||
Linker linker(*linkerInput);
|
||||
Linker::SegmentInfo globals;
|
||||
Linker::SegmentInfo constants;
|
||||
@ -276,4 +277,36 @@ void Program::processDebugData(uint32_t rootDeviceIndex) {
|
||||
}
|
||||
}
|
||||
|
||||
Debug::Segments Program::getZebinSegments(uint32_t rootDeviceIndex) {
|
||||
ArrayRef<const uint8_t> strings = {reinterpret_cast<const uint8_t *>(buildInfos[rootDeviceIndex].constStringSectionData.initData),
|
||||
buildInfos[rootDeviceIndex].constStringSectionData.size};
|
||||
std::vector<std::pair<std::string_view, NEO::GraphicsAllocation *>> kernels;
|
||||
for (const auto &kernelInfo : buildInfos[rootDeviceIndex].kernelInfoArray)
|
||||
kernels.push_back({kernelInfo->kernelDescriptor.kernelMetadata.kernelName, kernelInfo->getGraphicsAllocation()});
|
||||
|
||||
return Debug::Segments(getGlobalSurface(rootDeviceIndex), getConstantSurface(rootDeviceIndex), strings, kernels);
|
||||
}
|
||||
|
||||
void Program::createDebugZebin(uint32_t rootDeviceIndex) {
|
||||
if (debugDataSize != 0) {
|
||||
return;
|
||||
}
|
||||
auto refBin = ArrayRef<const uint8_t>(reinterpret_cast<const uint8_t *>(buildInfos[rootDeviceIndex].unpackedDeviceBinary.get()), buildInfos[rootDeviceIndex].unpackedDeviceBinarySize);
|
||||
auto segments = getZebinSegments(rootDeviceIndex);
|
||||
auto debugZebin = Debug::createDebugZebin(refBin, segments);
|
||||
|
||||
debugDataSize = debugZebin.size();
|
||||
debugData.reset(new char[debugDataSize]);
|
||||
memcpy_s(debugData.get(), debugDataSize,
|
||||
debugZebin.data(), debugZebin.size());
|
||||
}
|
||||
|
||||
void Program::createDebugData(uint32_t rootDeviceIndex) {
|
||||
auto refBin = ArrayRef<const uint8_t>(reinterpret_cast<const uint8_t *>(buildInfos[rootDeviceIndex].unpackedDeviceBinary.get()), buildInfos[rootDeviceIndex].unpackedDeviceBinarySize);
|
||||
if (isDeviceBinaryFormat<DeviceBinaryFormat::Zebin>(refBin)) {
|
||||
createDebugZebin(rootDeviceIndex);
|
||||
} else {
|
||||
processDebugData(rootDeviceIndex);
|
||||
}
|
||||
}
|
||||
} // namespace NEO
|
||||
|
@ -8,6 +8,7 @@
|
||||
#pragma once
|
||||
#include "shared/source/compiler_interface/compiler_interface.h"
|
||||
#include "shared/source/compiler_interface/linker.h"
|
||||
#include "shared/source/device_binary_format/debug_zebin.h"
|
||||
#include "shared/source/device_binary_format/elf/elf_encoder.h"
|
||||
#include "shared/source/helpers/non_copyable_or_moveable.h"
|
||||
#include "shared/source/program/program_info.h"
|
||||
@ -173,7 +174,7 @@ class Program : public BaseObject<_cl_program> {
|
||||
|
||||
cl_int getSource(std::string &binary) const;
|
||||
|
||||
void processDebugData(uint32_t rootDeviceIndex);
|
||||
MOCKABLE_VIRTUAL void processDebugData(uint32_t rootDeviceIndex);
|
||||
|
||||
void updateBuildLog(uint32_t rootDeviceIndex, const char *pErrorString, const size_t errorStringSize);
|
||||
|
||||
@ -282,6 +283,10 @@ class Program : public BaseObject<_cl_program> {
|
||||
this->context = pContext;
|
||||
}
|
||||
|
||||
void createDebugData(uint32_t rootDeviceIndex);
|
||||
MOCKABLE_VIRTUAL void createDebugZebin(uint32_t rootDeviceIndex);
|
||||
Debug::Segments getZebinSegments(uint32_t rootDeviceIndex);
|
||||
|
||||
protected:
|
||||
MOCKABLE_VIRTUAL cl_int createProgramFromBinary(const void *pBinary, size_t binarySize, ClDevice &clDevice);
|
||||
|
||||
@ -350,6 +355,7 @@ class Program : public BaseObject<_cl_program> {
|
||||
|
||||
std::unique_ptr<char[]> packedDeviceBinary;
|
||||
size_t packedDeviceBinarySize = 0U;
|
||||
ProgramInfo::GlobalSurfaceInfo constStringSectionData;
|
||||
};
|
||||
|
||||
std::vector<BuildInfo> buildInfos;
|
||||
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (C) 2018-2021 Intel Corporation
|
||||
# Copyright (C) 2018-2022 Intel Corporation
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
#
|
||||
@ -25,6 +25,9 @@ set(IGDRCL_SRCS_tests_program
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/program_with_block_kernels_tests.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/program_with_kernel_debug_tests.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/program_with_source.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/program_with_zebin.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/program_with_zebin.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/program_with_zebin_tests.cpp
|
||||
)
|
||||
|
||||
get_property(NEO_CORE_SRCS_tests_program GLOBAL PROPERTY NEO_CORE_SRCS_tests_program)
|
||||
|
61
opencl/test/unit_test/program/program_with_zebin.cpp
Normal file
61
opencl/test/unit_test/program/program_with_zebin.cpp
Normal file
@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright (C) 2022 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "opencl/test/unit_test/program/program_with_zebin.h"
|
||||
|
||||
#include "shared/test/unit_test/device_binary_format/zebin_tests.h"
|
||||
|
||||
#include "opencl/test/unit_test/mocks/mock_buffer.h"
|
||||
|
||||
using namespace NEO;
|
||||
|
||||
void ProgramWithZebinFixture::SetUp() {
|
||||
ProgramTests::SetUp();
|
||||
program = std::make_unique<MockProgram>(toClDeviceVector(*pClDevice));
|
||||
}
|
||||
|
||||
void ProgramWithZebinFixture::TearDown() {
|
||||
program->setGlobalSurface(nullptr);
|
||||
program->setConstantSurface(nullptr);
|
||||
program->getKernelInfoArray(rootDeviceIndex).clear();
|
||||
ProgramTests::TearDown();
|
||||
}
|
||||
|
||||
void ProgramWithZebinFixture::addEmptyZebin(NEO::MockProgram *program) {
|
||||
auto zebin = ZebinTestData::ValidEmptyProgram();
|
||||
|
||||
program->buildInfos[rootDeviceIndex].unpackedDeviceBinarySize = zebin.storage.size();
|
||||
program->buildInfos[rootDeviceIndex].unpackedDeviceBinary.reset(new char[zebin.storage.size()]);
|
||||
memcpy_s(program->buildInfos[rootDeviceIndex].unpackedDeviceBinary.get(), program->buildInfos[rootDeviceIndex].unpackedDeviceBinarySize,
|
||||
zebin.storage.data(), zebin.storage.size());
|
||||
}
|
||||
|
||||
void ProgramWithZebinFixture::populateProgramWithSegments(NEO::MockProgram *program) {
|
||||
kernelInfo = std::make_unique<KernelInfo>();
|
||||
kernelInfo->kernelDescriptor.kernelMetadata.kernelName = kernelName;
|
||||
mockAlloc = std::make_unique<MockGraphicsAllocation>();
|
||||
kernelInfo->kernelAllocation = mockAlloc.get();
|
||||
|
||||
program->addKernelInfo(kernelInfo.get(), rootDeviceIndex);
|
||||
|
||||
globalSurface = std::make_unique<MockBuffer>();
|
||||
constantSurface = std::make_unique<MockBuffer>();
|
||||
program->setGlobalSurface(&globalSurface->mockGfxAllocation);
|
||||
program->setConstantSurface(&constantSurface->mockGfxAllocation);
|
||||
|
||||
program->buildInfos[rootDeviceIndex].constStringSectionData.initData = &strings;
|
||||
program->buildInfos[rootDeviceIndex].constStringSectionData.size = sizeof(strings);
|
||||
}
|
||||
|
||||
void ProgramWithDebugDataCreationFixture::SetUp() {
|
||||
ProgramWithZebinFixture::SetUp();
|
||||
programWithDebugDataCreation = std::make_unique<MockProgramWithDebugDataCreation>(toClDeviceVector(*pClDevice));
|
||||
}
|
||||
|
||||
void ProgramWithDebugDataCreationFixture::TearDown() {
|
||||
ProgramWithZebinFixture::TearDown();
|
||||
}
|
54
opencl/test/unit_test/program/program_with_zebin.h
Normal file
54
opencl/test/unit_test/program/program_with_zebin.h
Normal file
@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (C) 2022 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "opencl/test/unit_test/mocks/mock_program.h"
|
||||
#include "opencl/test/unit_test/program/program_tests.h"
|
||||
|
||||
using namespace NEO;
|
||||
|
||||
class MockBuffer;
|
||||
class ProgramWithZebinFixture : public ProgramTests {
|
||||
public:
|
||||
std::unique_ptr<MockProgram> program;
|
||||
std::unique_ptr<KernelInfo> kernelInfo;
|
||||
std::unique_ptr<MockGraphicsAllocation> mockAlloc;
|
||||
std::unique_ptr<MockBuffer> globalSurface;
|
||||
std::unique_ptr<MockBuffer> constantSurface;
|
||||
const char strings[12] = "Hello olleH";
|
||||
const char kernelName[8] = "kernel1";
|
||||
void SetUp() override;
|
||||
void TearDown() override;
|
||||
void addEmptyZebin(MockProgram *program);
|
||||
void populateProgramWithSegments(MockProgram *program);
|
||||
~ProgramWithZebinFixture() = default;
|
||||
};
|
||||
|
||||
class ProgramWithDebugDataCreationFixture : public ProgramWithZebinFixture {
|
||||
|
||||
class MockProgramWithDebugDataCreation : public MockProgram {
|
||||
public:
|
||||
using Program::createDebugData;
|
||||
MockProgramWithDebugDataCreation(const ClDeviceVector &deviceVector) : MockProgram(deviceVector) {
|
||||
}
|
||||
~MockProgramWithDebugDataCreation() {
|
||||
}
|
||||
bool wasProcessDebugDataCalled = false;
|
||||
void processDebugData(uint32_t rootDeviceIndex) override {
|
||||
wasProcessDebugDataCalled = true;
|
||||
}
|
||||
bool wasCreateDebugZebinCalled = false;
|
||||
void createDebugZebin(uint32_t rootDeviceIndex) override {
|
||||
wasCreateDebugZebinCalled = true;
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
std::unique_ptr<MockProgramWithDebugDataCreation> programWithDebugDataCreation;
|
||||
void SetUp() override;
|
||||
void TearDown() override;
|
||||
};
|
82
opencl/test/unit_test/program/program_with_zebin_tests.cpp
Normal file
82
opencl/test/unit_test/program/program_with_zebin_tests.cpp
Normal file
@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright (C) 2022 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "shared/test/common/test_macros/test.h"
|
||||
|
||||
#include "opencl/test/unit_test/mocks/mock_buffer.h"
|
||||
#include "opencl/test/unit_test/program/program_with_zebin.h"
|
||||
|
||||
#include <memory>
|
||||
using namespace NEO;
|
||||
|
||||
TEST_F(ProgramWithZebinFixture, givenNoZebinThenSegmentsAreEmpty) {
|
||||
auto segments = program->getZebinSegments(pClDevice->getRootDeviceIndex());
|
||||
|
||||
EXPECT_EQ(std::numeric_limits<uintptr_t>::max(), segments.constData.address);
|
||||
EXPECT_TRUE(segments.constData.data.empty());
|
||||
|
||||
EXPECT_EQ(std::numeric_limits<uintptr_t>::max(), segments.varData.address);
|
||||
EXPECT_TRUE(segments.varData.data.empty());
|
||||
|
||||
EXPECT_EQ(std::numeric_limits<uintptr_t>::max(), segments.stringData.address);
|
||||
EXPECT_TRUE(segments.stringData.data.empty());
|
||||
|
||||
EXPECT_TRUE(segments.nameToSegMap.empty());
|
||||
}
|
||||
|
||||
TEST_F(ProgramWithZebinFixture, givenZebinSegmentsThenSegmentsArePopulated) {
|
||||
populateProgramWithSegments(program.get());
|
||||
auto segments = program->getZebinSegments(rootDeviceIndex);
|
||||
|
||||
auto checkGPUSeg = [](NEO::GraphicsAllocation *alloc, NEO::Debug::Segments::Segment segment) {
|
||||
EXPECT_EQ(static_cast<uintptr_t>(alloc->getGpuAddressToPatch()), segment.address);
|
||||
EXPECT_EQ(reinterpret_cast<uint8_t *>(alloc->getUnderlyingBuffer()), segment.data.begin());
|
||||
EXPECT_EQ(static_cast<size_t>(alloc->getUnderlyingBufferSize()), segment.data.size());
|
||||
};
|
||||
checkGPUSeg(program->buildInfos[rootDeviceIndex].constantSurface, segments.constData);
|
||||
checkGPUSeg(program->buildInfos[rootDeviceIndex].globalSurface, segments.varData);
|
||||
checkGPUSeg(program->getKernelInfoArray(rootDeviceIndex)[0]->getGraphicsAllocation(), segments.nameToSegMap["kernel1"]);
|
||||
|
||||
EXPECT_EQ(reinterpret_cast<uintptr_t>(program->buildInfos[rootDeviceIndex].constStringSectionData.initData), segments.stringData.address);
|
||||
EXPECT_EQ(reinterpret_cast<const uint8_t *>(program->buildInfos[rootDeviceIndex].constStringSectionData.initData), segments.stringData.data.begin());
|
||||
EXPECT_EQ(program->buildInfos[rootDeviceIndex].constStringSectionData.size, segments.stringData.data.size());
|
||||
}
|
||||
|
||||
TEST_F(ProgramWithZebinFixture, givenNonEmptyDebugDataThenDebugZebinIsNotCreated) {
|
||||
addEmptyZebin(program.get());
|
||||
populateProgramWithSegments(program.get());
|
||||
program->debugDataSize = 8u;
|
||||
program->debugData.reset(nullptr);
|
||||
program->createDebugZebin(rootDeviceIndex);
|
||||
EXPECT_EQ(nullptr, program->debugData.get());
|
||||
}
|
||||
|
||||
TEST_F(ProgramWithZebinFixture, givenEmptyDebugDataThenDebugZebinIsCreatedAndStoredInDebugData) {
|
||||
addEmptyZebin(program.get());
|
||||
populateProgramWithSegments(program.get());
|
||||
|
||||
program->debugDataSize = 0u;
|
||||
program->debugData.reset(nullptr);
|
||||
program->createDebugZebin(rootDeviceIndex);
|
||||
EXPECT_NE(nullptr, program->debugData.get());
|
||||
}
|
||||
|
||||
TEST_F(ProgramWithDebugDataCreationFixture, givenZebinaryFormatInCreateDebugDataThenCreateDebugZebinIsCalled) {
|
||||
addEmptyZebin(programWithDebugDataCreation.get());
|
||||
programWithDebugDataCreation->createDebugData(rootDeviceIndex);
|
||||
EXPECT_TRUE(programWithDebugDataCreation->wasCreateDebugZebinCalled);
|
||||
EXPECT_FALSE(programWithDebugDataCreation->wasProcessDebugDataCalled);
|
||||
}
|
||||
|
||||
TEST_F(ProgramWithDebugDataCreationFixture, givenNonZebinaryFormatInCreateDebugDataThenProcessDebugDataIsCalled) {
|
||||
size_t fakeBinarySize = 8u;
|
||||
programWithDebugDataCreation->buildInfos[rootDeviceIndex].unpackedDeviceBinarySize = fakeBinarySize;
|
||||
programWithDebugDataCreation->buildInfos[rootDeviceIndex].unpackedDeviceBinary.reset(new char[fakeBinarySize]);
|
||||
programWithDebugDataCreation->createDebugData(rootDeviceIndex);
|
||||
EXPECT_FALSE(programWithDebugDataCreation->wasCreateDebugZebinCalled);
|
||||
EXPECT_TRUE(programWithDebugDataCreation->wasProcessDebugDataCalled);
|
||||
}
|
Reference in New Issue
Block a user