From 741ee49c9a048452bced35a35cbdc084bf1a668b Mon Sep 17 00:00:00 2001 From: Kacper Nowak Date: Wed, 9 Feb 2022 13:18:18 +0000 Subject: [PATCH] Refactor source level debugger notification in OCL. [1/n] Refactor source level debugger notification in OCL path - in build() cl_program method. It fixes confusing debug data creation (mixed legacy/zebin path) and thus incorrect kernel notification about debug data. Signed-off-by: Kacper Nowak Related-To: NEO-6644 --- opencl/source/program/build.cpp | 25 +++-- opencl/test/unit_test/mocks/mock_program.h | 14 ++- .../program_with_kernel_debug_tests.cpp | 12 +++ .../unit_test/program/program_with_zebin.cpp | 12 --- .../unit_test/program/program_with_zebin.h | 26 ----- .../program/program_with_zebin_tests.cpp | 100 ++++++++++++------ 6 files changed, 113 insertions(+), 76 deletions(-) diff --git a/opencl/source/program/build.cpp b/opencl/source/program/build.cpp index fa0ceeec3b..44c3f4d547 100644 --- a/opencl/source/program/build.cpp +++ b/opencl/source/program/build.cpp @@ -186,13 +186,24 @@ cl_int Program::build( if (BuildPhase::DebugDataNotification == phaseReached[rootDeviceIndex]) { continue; } - createDebugData(clDevice->getRootDeviceIndex()); - if (clDevice->getSourceLevelDebugger()) { - for (auto kernelInfo : buildInfos[rootDeviceIndex].kernelInfoArray) { - clDevice->getSourceLevelDebugger()->notifyKernelDebugData(&kernelInfo->debugData, - kernelInfo->kernelDescriptor.kernelMetadata.kernelName, - kernelInfo->heapInfo.pKernelHeap, - kernelInfo->heapInfo.KernelHeapSize); + auto refBin = ArrayRef(reinterpret_cast(this->buildInfos[clDevice->getRootDeviceIndex()].unpackedDeviceBinary.get()), this->buildInfos[clDevice->getRootDeviceIndex()].unpackedDeviceBinarySize); + if (NEO::isDeviceBinaryFormat(refBin)) { + createDebugZebin(clDevice->getRootDeviceIndex()); + if (clDevice->getSourceLevelDebugger()) { + NEO::DebugData debugData; + debugData.vIsa = reinterpret_cast(this->buildInfos[clDevice->getRootDeviceIndex()].debugData.get()); + debugData.vIsaSize = static_cast(this->buildInfos[clDevice->getRootDeviceIndex()].debugDataSize); + clDevice->getSourceLevelDebugger()->notifyKernelDebugData(&debugData, "debug_zebin", nullptr, 0); + } + } else { + processDebugData(clDevice->getRootDeviceIndex()); + if (clDevice->getSourceLevelDebugger()) { + for (auto kernelInfo : buildInfos[rootDeviceIndex].kernelInfoArray) { + clDevice->getSourceLevelDebugger()->notifyKernelDebugData(&kernelInfo->debugData, + kernelInfo->kernelDescriptor.kernelMetadata.kernelName, + kernelInfo->heapInfo.pKernelHeap, + kernelInfo->heapInfo.KernelHeapSize); + } } } phaseReached[rootDeviceIndex] = BuildPhase::DebugDataNotification; diff --git a/opencl/test/unit_test/mocks/mock_program.h b/opencl/test/unit_test/mocks/mock_program.h index bff1bca2ea..6f6a0e5853 100644 --- a/opencl/test/unit_test/mocks/mock_program.h +++ b/opencl/test/unit_test/mocks/mock_program.h @@ -32,7 +32,6 @@ class MockProgram : public Program { using Program::areSpecializationConstantsInitialized; using Program::buildInfos; using Program::context; - using Program::createDebugZebin; using Program::createdFrom; using Program::createProgramFromBinary; using Program::deviceBuildInfos; @@ -42,6 +41,7 @@ class MockProgram : public Program { using Program::irBinary; using Program::irBinarySize; using Program::isBuiltIn; + using Program::isCreatedFromBinary; using Program::isSpirV; using Program::kernelDebugEnabled; using Program::linkBinary; @@ -179,12 +179,24 @@ class MockProgram : public Program { return kernelInfos; } + void processDebugData(uint32_t rootDeviceIndex) override { + Program::processDebugData(rootDeviceIndex); + wasProcessDebugDataCalled = true; + } + + void createDebugZebin(uint32_t rootDeviceIndex) override { + Program::createDebugZebin(rootDeviceIndex); + wasCreateDebugZebinCalled = true; + } + std::map processGenBinaryCalledPerRootDevice; std::map replaceDeviceBinaryCalledPerRootDevice; static int getInternalOptionsCalled; bool contextSet = false; int isFlagOptionOverride = -1; int isOptionValueValidOverride = -1; + bool wasProcessDebugDataCalled = false; + bool wasCreateDebugZebinCalled = false; }; class MockProgramAppendKernelDebugOptions : public Program { diff --git a/opencl/test/unit_test/program/program_with_kernel_debug_tests.cpp b/opencl/test/unit_test/program/program_with_kernel_debug_tests.cpp index b1ebcb84bf..93da30ffb7 100644 --- a/opencl/test/unit_test/program/program_with_kernel_debug_tests.cpp +++ b/opencl/test/unit_test/program/program_with_kernel_debug_tests.cpp @@ -353,3 +353,15 @@ TEST_F(ProgramWithKernelDebuggingTest, givenProgramWithKernelDebugEnabledWhenPro EXPECT_NE(0u, kernelInfo->debugData.vIsaSize); EXPECT_NE(nullptr, kernelInfo->debugData.vIsa); } + +TEST_F(ProgramWithKernelDebuggingTest, givenProgramWithNonZebinaryFormatAndKernelDebugEnabledWhenProgramIsBuiltThenProcessDebugDataIsCalledAndDebuggerNotified) { + MockSourceLevelDebugger *sourceLevelDebugger = new MockSourceLevelDebugger; + pDevice->executionEnvironment->rootDeviceEnvironments[pDevice->getRootDeviceIndex()]->debugger.reset(sourceLevelDebugger); + pProgram->enableKernelDebug(); + + cl_int retVal = pProgram->build(pProgram->getDevices(), nullptr, false); + EXPECT_EQ(CL_SUCCESS, retVal); + EXPECT_FALSE(pProgram->wasCreateDebugZebinCalled); + EXPECT_TRUE(pProgram->wasProcessDebugDataCalled); + EXPECT_EQ(1u, sourceLevelDebugger->notifyKernelDebugDataCalled); +} \ No newline at end of file diff --git a/opencl/test/unit_test/program/program_with_zebin.cpp b/opencl/test/unit_test/program/program_with_zebin.cpp index 3acfe6848a..a9d26fe952 100644 --- a/opencl/test/unit_test/program/program_with_zebin.cpp +++ b/opencl/test/unit_test/program/program_with_zebin.cpp @@ -49,16 +49,4 @@ void ProgramWithZebinFixture::populateProgramWithSegments(NEO::MockProgram *prog program->buildInfos[rootDeviceIndex].constStringSectionData.initData = &strings; program->buildInfos[rootDeviceIndex].constStringSectionData.size = sizeof(strings); -} - -void ProgramWithDebugDataCreationFixture::SetUp() { - ProgramWithZebinFixture::SetUp(); - programWithDebugDataCreation = std::make_unique(toClDeviceVector(*pClDevice)); -} - -void ProgramWithDebugDataCreationFixture::TearDown() { - programWithDebugDataCreation->setGlobalSurface(nullptr); - programWithDebugDataCreation->setConstantSurface(nullptr); - programWithDebugDataCreation->getKernelInfoArray(rootDeviceIndex).clear(); - ProgramWithZebinFixture::TearDown(); } \ No newline at end of file diff --git a/opencl/test/unit_test/program/program_with_zebin.h b/opencl/test/unit_test/program/program_with_zebin.h index 520382bf31..30b9326c31 100644 --- a/opencl/test/unit_test/program/program_with_zebin.h +++ b/opencl/test/unit_test/program/program_with_zebin.h @@ -26,30 +26,4 @@ class ProgramWithZebinFixture : public ProgramTests { 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 { - MockProgram::createDebugZebin(rootDeviceIndex); - wasCreateDebugZebinCalled = true; - } - }; - - public: - std::unique_ptr programWithDebugDataCreation; - void SetUp() override; - void TearDown() override; }; \ No newline at end of file diff --git a/opencl/test/unit_test/program/program_with_zebin_tests.cpp b/opencl/test/unit_test/program/program_with_zebin_tests.cpp index 422fbe9a8a..a842bd1688 100644 --- a/opencl/test/unit_test/program/program_with_zebin_tests.cpp +++ b/opencl/test/unit_test/program/program_with_zebin_tests.cpp @@ -5,6 +5,7 @@ * */ +#include "shared/test/common/mocks/mock_source_level_debugger.h" #include "shared/test/common/test_macros/test.h" #include "opencl/test/unit_test/mocks/mock_buffer.h" @@ -64,41 +65,41 @@ TEST_F(ProgramWithZebinFixture, givenEmptyDebugDataThenDebugZebinIsCreatedAndSto EXPECT_NE(nullptr, program->buildInfos[rootDeviceIndex].debugData.get()); } -TEST_F(ProgramWithDebugDataCreationFixture, givenZebinaryFormatInCreateDebugDataThenCreateDebugZebinIsCalled) { - addEmptyZebin(programWithDebugDataCreation.get()); - programWithDebugDataCreation->createDebugData(rootDeviceIndex); - EXPECT_TRUE(programWithDebugDataCreation->wasCreateDebugZebinCalled); - EXPECT_FALSE(programWithDebugDataCreation->wasProcessDebugDataCalled); +TEST_F(ProgramWithZebinFixture, givenZebinaryFormatInCreateDebugDataThenCreateDebugZebinIsCalled) { + addEmptyZebin(program.get()); + program->createDebugData(rootDeviceIndex); + EXPECT_TRUE(program->wasCreateDebugZebinCalled); + EXPECT_FALSE(program->wasProcessDebugDataCalled); } -TEST_F(ProgramWithDebugDataCreationFixture, givenNonZebinaryFormatInCreateDebugDataThenProcessDebugDataIsCalled) { +TEST_F(ProgramWithZebinFixture, 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); + program->buildInfos[rootDeviceIndex].unpackedDeviceBinarySize = fakeBinarySize; + program->buildInfos[rootDeviceIndex].unpackedDeviceBinary.reset(new char[fakeBinarySize]); + program->createDebugData(rootDeviceIndex); + EXPECT_FALSE(program->wasCreateDebugZebinCalled); + EXPECT_TRUE(program->wasProcessDebugDataCalled); } -TEST_F(ProgramWithDebugDataCreationFixture, givenEmptyDebugDataAndZebinBinaryFormatThenCreateDebugZebinAndReturnOnGetInfo) { - addEmptyZebin(programWithDebugDataCreation.get()); - populateProgramWithSegments(programWithDebugDataCreation.get()); - programWithDebugDataCreation->buildInfos[rootDeviceIndex].debugDataSize = 0u; - programWithDebugDataCreation->buildInfos[rootDeviceIndex].debugData.reset(nullptr); +TEST_F(ProgramWithZebinFixture, givenEmptyDebugDataAndZebinBinaryFormatThenCreateDebugZebinAndReturnOnGetInfo) { + addEmptyZebin(program.get()); + populateProgramWithSegments(program.get()); + program->buildInfos[rootDeviceIndex].debugDataSize = 0u; + program->buildInfos[rootDeviceIndex].debugData.reset(nullptr); - EXPECT_FALSE(programWithDebugDataCreation->wasCreateDebugZebinCalled); + EXPECT_FALSE(program->wasCreateDebugZebinCalled); auto retVal = CL_INVALID_VALUE; size_t debugDataSize = 0; - retVal = programWithDebugDataCreation->getInfo(CL_PROGRAM_DEBUG_INFO_SIZES_INTEL, sizeof(debugDataSize), &debugDataSize, nullptr); + retVal = program->getInfo(CL_PROGRAM_DEBUG_INFO_SIZES_INTEL, sizeof(debugDataSize), &debugDataSize, nullptr); EXPECT_EQ(CL_SUCCESS, retVal); - EXPECT_NE(nullptr, programWithDebugDataCreation->buildInfos[rootDeviceIndex].debugData); - EXPECT_TRUE(programWithDebugDataCreation->wasCreateDebugZebinCalled); + EXPECT_NE(nullptr, program->buildInfos[rootDeviceIndex].debugData); + EXPECT_TRUE(program->wasCreateDebugZebinCalled); - programWithDebugDataCreation->wasCreateDebugZebinCalled = false; + program->wasCreateDebugZebinCalled = false; - retVal = programWithDebugDataCreation->getInfo(CL_PROGRAM_DEBUG_INFO_SIZES_INTEL, sizeof(debugDataSize), &debugDataSize, nullptr); + retVal = program->getInfo(CL_PROGRAM_DEBUG_INFO_SIZES_INTEL, sizeof(debugDataSize), &debugDataSize, nullptr); EXPECT_EQ(CL_SUCCESS, retVal); - EXPECT_FALSE(programWithDebugDataCreation->wasCreateDebugZebinCalled); + EXPECT_FALSE(program->wasCreateDebugZebinCalled); std::unique_ptr debugData = std::make_unique(debugDataSize); for (size_t n = 0; n < sizeof(debugData); n++) { @@ -107,12 +108,12 @@ TEST_F(ProgramWithDebugDataCreationFixture, givenEmptyDebugDataAndZebinBinaryFor char *pDebugData = &debugData[0]; size_t retData = 0; - retVal = programWithDebugDataCreation->getInfo(CL_PROGRAM_DEBUG_INFO_INTEL, debugDataSize, &pDebugData, &retData); + retVal = program->getInfo(CL_PROGRAM_DEBUG_INFO_INTEL, debugDataSize, &pDebugData, &retData); EXPECT_EQ(CL_SUCCESS, retVal); - EXPECT_FALSE(programWithDebugDataCreation->wasCreateDebugZebinCalled); + EXPECT_FALSE(program->wasCreateDebugZebinCalled); - programWithDebugDataCreation->buildInfos[rootDeviceIndex].debugDataSize = 0u; - programWithDebugDataCreation->buildInfos[rootDeviceIndex].debugData.reset(nullptr); + program->buildInfos[rootDeviceIndex].debugDataSize = 0u; + program->buildInfos[rootDeviceIndex].debugData.reset(nullptr); std::unique_ptr debugData2 = std::make_unique(debugDataSize); for (size_t n = 0; n < sizeof(debugData2); n++) { @@ -120,12 +121,51 @@ TEST_F(ProgramWithDebugDataCreationFixture, givenEmptyDebugDataAndZebinBinaryFor } char *pDebugData2 = &debugData2[0]; size_t retData2 = 0; - retVal = programWithDebugDataCreation->getInfo(CL_PROGRAM_DEBUG_INFO_INTEL, debugDataSize, &pDebugData2, &retData2); + retVal = program->getInfo(CL_PROGRAM_DEBUG_INFO_INTEL, debugDataSize, &pDebugData2, &retData2); EXPECT_EQ(CL_SUCCESS, retVal); - EXPECT_TRUE(programWithDebugDataCreation->wasCreateDebugZebinCalled); + EXPECT_TRUE(program->wasCreateDebugZebinCalled); cl_uint numDevices; - retVal = clGetProgramInfo(programWithDebugDataCreation.get(), CL_PROGRAM_NUM_DEVICES, sizeof(numDevices), &numDevices, nullptr); + retVal = clGetProgramInfo(program.get(), CL_PROGRAM_NUM_DEVICES, sizeof(numDevices), &numDevices, nullptr); EXPECT_EQ(CL_SUCCESS, retVal); EXPECT_EQ(numDevices * sizeof(debugData), retData); +} + +TEST_F(ProgramWithZebinFixture, givenZebinBinaryFormatWhenProgramIsBuiltWithKernelDebugEnabledAndDebuggerAvailableThenDebugZebinCreationIsCalledAndDebuggerNotified) { + addEmptyZebin(program.get()); + + MockSourceLevelDebugger *sourceLevelDebugger = new MockSourceLevelDebugger; + sourceLevelDebugger->setActive(true); + pClDevice->getExecutionEnvironment()->rootDeviceEnvironments[pDevice->getRootDeviceIndex()]->debugger.reset(sourceLevelDebugger); + + program->createdFrom = Program::CreatedFrom::BINARY; + program->isCreatedFromBinary = true; + program->enableKernelDebug(); + auto retVal = program->build( + program->getDevices(), + nullptr, + false); + + EXPECT_EQ(CL_SUCCESS, retVal); + EXPECT_TRUE(program->wasCreateDebugZebinCalled); + EXPECT_FALSE(program->wasProcessDebugDataCalled); + EXPECT_EQ(1u, sourceLevelDebugger->notifyKernelDebugDataCalled); +} + +TEST_F(ProgramWithZebinFixture, givenZebinBinaryFormatWhenProgramIsBuiltWithKernelDebugEnabledAndNoDebuggerThenDebugZebinCreationIsCalled) { + addEmptyZebin(program.get()); + + pClDevice->getExecutionEnvironment()->rootDeviceEnvironments[pDevice->getRootDeviceIndex()]->debugger.reset(nullptr); + + program->createdFrom = Program::CreatedFrom::BINARY; + program->isCreatedFromBinary = true; + program->enableKernelDebug(); + auto retVal = program->build( + program->getDevices(), + nullptr, + false); + + EXPECT_EQ(CL_SUCCESS, retVal); + EXPECT_TRUE(program->wasCreateDebugZebinCalled); + EXPECT_FALSE(program->wasProcessDebugDataCalled); } \ No newline at end of file