From 359b9278b8e57b928289c3cfd56d4d68e563c4d0 Mon Sep 17 00:00:00 2001 From: Krystian Chmielewski Date: Fri, 25 Nov 2022 11:35:36 +0000 Subject: [PATCH] fix(ocl zebin): do not expose functions as kernel Do not expose dummy kernel containing functions' ISAs as kernels. Signed-off-by: Krystian Chmielewski --- .../source/program/process_device_binary.cpp | 15 ++++++++- opencl/source/program/program.h | 2 ++ .../unit_test/fixtures/program_fixture.cpp | 18 +++++++++++ .../test/unit_test/fixtures/program_fixture.h | 32 +++++++++++++------ opencl/test/unit_test/mocks/mock_program.h | 17 ++++++++++ .../test/unit_test/program/program_tests.cpp | 19 +++++++++++ 6 files changed, 93 insertions(+), 10 deletions(-) diff --git a/opencl/source/program/process_device_binary.cpp b/opencl/source/program/process_device_binary.cpp index 0550af5ad5..460b309f8a 100644 --- a/opencl/source/program/process_device_binary.cpp +++ b/opencl/source/program/process_device_binary.cpp @@ -38,6 +38,10 @@ const KernelInfo *Program::getKernelInfo( return nullptr; } + if (kernelName == NEO::Elf::SectionsNamesZebin::externalFunctions) { + return nullptr; + } + auto &kernelInfoArray = buildInfos[rootDeviceIndex].kernelInfoArray; auto it = std::find_if(kernelInfoArray.begin(), kernelInfoArray.end(), @@ -47,11 +51,19 @@ const KernelInfo *Program::getKernelInfo( } size_t Program::getNumKernels() const { - return buildInfos[clDevices[0]->getRootDeviceIndex()].kernelInfoArray.size(); + auto numKernels = buildInfos[clDevices[0]->getRootDeviceIndex()].kernelInfoArray.size(); + auto usesExportedFunctions = (exportedFunctionsKernelId != std::numeric_limits::max()); + if (usesExportedFunctions) { + numKernels--; + } + return numKernels; } const KernelInfo *Program::getKernelInfo(size_t ordinal, uint32_t rootDeviceIndex) const { auto &kernelInfoArray = buildInfos[rootDeviceIndex].kernelInfoArray; + if (exportedFunctionsKernelId == ordinal) { + ordinal++; + } DEBUG_BREAK_IF(ordinal >= kernelInfoArray.size()); return kernelInfoArray[ordinal]; } @@ -85,6 +97,7 @@ cl_int Program::linkBinary(Device *pDevice, const void *constantsInitData, size_ strings.segmentSize = stringsInfo.size; } if (linkerInput->getExportedFunctionsSegmentId() >= 0) { + exportedFunctionsKernelId = static_cast(linkerInput->getExportedFunctionsSegmentId()); // Exported functions reside in instruction heap of one of kernels auto exportedFunctionHeapId = linkerInput->getExportedFunctionsSegmentId(); buildInfos[rootDeviceIndex].exportedFunctionsSurface = kernelInfoArray[exportedFunctionHeapId]->getGraphicsAllocation(); diff --git a/opencl/source/program/program.h b/opencl/source/program/program.h index af516a1c0d..46f3ae72ad 100644 --- a/opencl/source/program/program.h +++ b/opencl/source/program/program.h @@ -370,6 +370,8 @@ class Program : public BaseObject<_cl_program> { std::mutex lockMutex; uint32_t exposedKernels = 0; + size_t exportedFunctionsKernelId = std::numeric_limits::max(); + std::once_flag extractAndDecodeMetadataOnce; }; diff --git a/opencl/test/unit_test/fixtures/program_fixture.cpp b/opencl/test/unit_test/fixtures/program_fixture.cpp index 3b3609e9b3..6be8fc28e4 100644 --- a/opencl/test/unit_test/fixtures/program_fixture.cpp +++ b/opencl/test/unit_test/fixtures/program_fixture.cpp @@ -8,6 +8,7 @@ #include "opencl/test/unit_test/fixtures/program_fixture.h" #include "opencl/source/program/create.inl" +#include "opencl/test/unit_test/mocks/mock_context.h" #include "opencl/test/unit_test/mocks/mock_program.h" namespace NEO { @@ -40,6 +41,13 @@ void ProgramFixture::createProgramWithSource(Context *pContext, ASSERT_EQ(CL_SUCCESS, retVal); } +void ProgramFixture::cleanup() { + if (pProgram != nullptr) { + pProgram->release(); + } + knownSource.reset(); +} + void ProgramFixture::createProgramFromBinary(Context *pContext, const ClDeviceVector &deviceVector, const std::string &binaryFileName, @@ -83,4 +91,14 @@ void ProgramFixture::createProgramFromBinary(Context *pContext, ASSERT_EQ(CL_SUCCESS, retVal); } +NEOProgramFixture::NEOProgramFixture() = default; +NEOProgramFixture::~NEOProgramFixture() = default; + +void NEOProgramFixture::setUp() { + context = std::make_unique(); + program = std::make_unique(context.get(), false, context->getDevices()); +} + +void NEOProgramFixture::tearDown() {} + } // namespace NEO diff --git a/opencl/test/unit_test/fixtures/program_fixture.h b/opencl/test/unit_test/fixtures/program_fixture.h index 19d3bdc5e4..7dad323a91 100644 --- a/opencl/test/unit_test/fixtures/program_fixture.h +++ b/opencl/test/unit_test/fixtures/program_fixture.h @@ -9,12 +9,31 @@ #include "shared/source/helpers/file_io.h" #include "shared/test/common/helpers/test_files.h" -#include "opencl/source/program/program.h" -#include "opencl/test/unit_test/mocks/mock_program.h" - #include "gtest/gtest.h" +#include +#include + namespace NEO { +class Context; +class ClDeviceVector; +class MockContext; +class MockProgram; +class ClDevice; +class MockNeoProgram; +using cl_int = int; + +class NEOProgramFixture { + public: + NEOProgramFixture(); + ~NEOProgramFixture(); + + protected: + void setUp(); + void tearDown(); + std::unique_ptr context; + std::unique_ptr program; +}; class ProgramFixture { public: @@ -40,12 +59,7 @@ class ProgramFixture { cleanup(); } - void cleanup() { - if (pProgram != nullptr) { - pProgram->release(); - } - knownSource.reset(); - } + void cleanup(); MockProgram *pProgram = nullptr; std::unique_ptr knownSource; diff --git a/opencl/test/unit_test/mocks/mock_program.h b/opencl/test/unit_test/mocks/mock_program.h index 5629f63142..bb0a19f037 100644 --- a/opencl/test/unit_test/mocks/mock_program.h +++ b/opencl/test/unit_test/mocks/mock_program.h @@ -25,6 +25,23 @@ ClDeviceVector toClDeviceVector(ClDevice &clDevice); //////////////////////////////////////////////////////////////////////////////// // Program - Core implementation //////////////////////////////////////////////////////////////////////////////// +class MockNeoProgram : public NEO::Program { + public: + using Base = NEO::Program; + using Base::buildInfos; + using Base::exportedFunctionsKernelId; + + MockNeoProgram(NEO::Context *context, bool isBuiltIn, const NEO::ClDeviceVector &devices) + : NEO::Program(context, isBuiltIn, devices) {} + + void resizeAndPopulateKernelInfoArray(size_t size) { + buildInfos[0].kernelInfoArray.resize(size); + for (auto &entry : buildInfos[0].kernelInfoArray) { + entry = new KernelInfo(); + } + } +}; + class MockProgram : public Program { public: using Program::allowNonUniform; diff --git a/opencl/test/unit_test/program/program_tests.cpp b/opencl/test/unit_test/program/program_tests.cpp index ad291dd15c..fbf0a806dc 100644 --- a/opencl/test/unit_test/program/program_tests.cpp +++ b/opencl/test/unit_test/program/program_tests.cpp @@ -565,6 +565,25 @@ TEST_F(ProgramFromBinaryTest, givenReuseKernelBinariesWhenCleanCurrentKernelInfo EXPECT_EQ(0u, kernelAllocMap.size()); } +using ProgramGetNumKernelsTest = Test; +TEST_F(ProgramGetNumKernelsTest, givenProgramWithFunctionsWhenGettingNumKernelsFunctionsAreNotExposed) { + program->resizeAndPopulateKernelInfoArray(2); + program->exportedFunctionsKernelId = 0; + EXPECT_EQ(1U, program->getNumKernels()); +} + +using ProgramGetKernelInfoTest = Test; +TEST_F(ProgramGetKernelInfoTest, givenProgramWithFunctionsWhenGettingKernelInfoByIndexThenFunctionsAreNotExposed) { + program->resizeAndPopulateKernelInfoArray(2); + program->exportedFunctionsKernelId = 0; + auto kernelInfo = program->getKernelInfo(size_t(0), uint32_t(0)); + EXPECT_EQ(program->buildInfos[0].kernelInfoArray[1], kernelInfo); +} + +TEST_F(ProgramGetKernelInfoTest, givenProgramFunctionsWhenGettingKernelInfoByNameThenFunctionsAreNotExposed) { + EXPECT_EQ(nullptr, program->getKernelInfo(NEO::Elf::SectionsNamesZebin::externalFunctions.data(), uint32_t(0))); +} + HWTEST_F(ProgramFromBinaryTest, givenProgramWhenCleanCurrentKernelInfoIsCalledButGpuIsNotYetDoneThenKernelAllocationIsPutOnDeferredFreeListAndCsrRegistersCacheFlush) { auto &csr = pDevice->getGpgpuCommandStreamReceiver(); EXPECT_TRUE(csr.getTemporaryAllocations().peekIsEmpty());